diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/freestyle/intern/stroke | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/freestyle/intern/stroke')
51 files changed, 10005 insertions, 9806 deletions
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp index 0047940a5b7..95d4735ddc4 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp @@ -29,81 +29,91 @@ namespace Freestyle { namespace Functions0D { -int DensityF0D::operator()(Interface0DIterator& iter) +int DensityF0D::operator()(Interface0DIterator &iter) { - Canvas *canvas = Canvas::getInstance(); - int bound = _filter.getBound(); - - if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound>canvas->width()) || - (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound>canvas->height())) - { - result = 0.0; - return 0; - } - - RGBImage image; - canvas->readColorPixels((int)iter->getProjectedX() - bound, (int)iter->getProjectedY() - bound, - _filter.maskSize(), _filter.maskSize(), image); - result = _filter.getSmoothedPixel<RGBImage>(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY()); - - return 0; + Canvas *canvas = Canvas::getInstance(); + int bound = _filter.getBound(); + + if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound > canvas->width()) || + (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound > canvas->height())) { + result = 0.0; + return 0; + } + + RGBImage image; + canvas->readColorPixels((int)iter->getProjectedX() - bound, + (int)iter->getProjectedY() - bound, + _filter.maskSize(), + _filter.maskSize(), + image); + result = _filter.getSmoothedPixel<RGBImage>( + &image, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + + return 0; } - -int LocalAverageDepthF0D::operator()(Interface0DIterator& iter) +int LocalAverageDepthF0D::operator()(Interface0DIterator &iter) { - Canvas *iViewer = Canvas::getInstance(); - int bound = _filter.getBound(); - - if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound>iViewer->width()) || - (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound>iViewer->height())) - { - result = 0.0; - return 0; - } - - GrayImage image; - iViewer->readDepthPixels((int)iter->getProjectedX() - bound, (int)iter->getProjectedY() - bound, - _filter.maskSize(), _filter.maskSize(), image); - result = _filter.getSmoothedPixel(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY()); - - return 0; + Canvas *iViewer = Canvas::getInstance(); + int bound = _filter.getBound(); + + if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound > iViewer->width()) || + (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound > iViewer->height())) { + result = 0.0; + return 0; + } + + GrayImage image; + iViewer->readDepthPixels((int)iter->getProjectedX() - bound, + (int)iter->getProjectedY() - bound, + _filter.maskSize(), + _filter.maskSize(), + image); + result = _filter.getSmoothedPixel( + &image, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + + return 0; } -int ReadMapPixelF0D::operator()(Interface0DIterator& iter) +int ReadMapPixelF0D::operator()(Interface0DIterator &iter) { - Canvas *canvas = Canvas::getInstance(); - result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); - return 0; + Canvas *canvas = Canvas::getInstance(); + result = canvas->readMapPixel( + _mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; } -int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) +int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator &iter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - result = svm->readSteerableViewMapPixel(_orientation, _level, (int)iter->getProjectedX(), - (int)iter->getProjectedY()); - return 0; + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readSteerableViewMapPixel( + _orientation, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; } -int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) +int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator &iter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - result = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); - return 0; + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readCompleteViewMapPixel( + _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; } -int GetViewMapGradientNormF0D::operator()(Interface0DIterator& iter) +int GetViewMapGradientNormF0D::operator()(Interface0DIterator &iter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - float pxy = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); - float gx = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX() + _step, - (int)iter->getProjectedY()) - pxy; - float gy = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(), - (int)iter->getProjectedY() + _step) - pxy; - result = Vec2f(gx, gy).norm(); - return 0; + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + float pxy = svm->readCompleteViewMapPixel( + _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); + float gx = svm->readCompleteViewMapPixel( + _level, (int)iter->getProjectedX() + _step, (int)iter->getProjectedY()) - + pxy; + float gy = svm->readCompleteViewMapPixel( + _level, (int)iter->getProjectedX(), (int)iter->getProjectedY() + _step) - + pxy; + result = Vec2f(gx, gy).norm(); + return 0; } -} // end of namespace Functions0D +} // end of namespace Functions0D } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h index 5889f3c4ed3..24c710bd163 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h @@ -41,179 +41,173 @@ namespace Functions0D { * This density is evaluated using a pixels square window around the evaluation point and integrating * these values using a gaussian. */ -class DensityF0D : public UnaryFunction0D<double> -{ -public: - /*! Builds the functor from the gaussian sigma value. - * \param sigma: - * sigma indicates the x value for which the gaussian function is 0.5. It leads to the window size value. - * (the larger, the smoother) - */ - DensityF0D(double sigma = 2) : UnaryFunction0D<double>() - { - _filter.setSigma((float)sigma); - } - - /*! Returns the string "DensityF0D" */ - string getName() const - { - return "DensityF0D"; - } - - /*! The () operator. */ - int operator()(Interface0DIterator& iter); - -private: - GaussianFilter _filter; +class DensityF0D : public UnaryFunction0D<double> { + public: + /*! Builds the functor from the gaussian sigma value. + * \param sigma: + * sigma indicates the x value for which the gaussian function is 0.5. It leads to the window size value. + * (the larger, the smoother) + */ + DensityF0D(double sigma = 2) : UnaryFunction0D<double>() + { + _filter.setSigma((float)sigma); + } + + /*! Returns the string "DensityF0D" */ + string getName() const + { + return "DensityF0D"; + } + + /*! The () operator. */ + int operator()(Interface0DIterator &iter); + + private: + GaussianFilter _filter; }; // LocalAverageDepthF0D /*! Returns the average depth around a point. * The result is obtained by querying the depth buffer on a window around that point. */ -class LocalAverageDepthF0D : public UnaryFunction0D<double> -{ -private: - GaussianFilter _filter; - -public: - /*! Builds the functor from the size of the mask that will be used. */ - LocalAverageDepthF0D(real maskSize = 5.0f) : UnaryFunction0D<double>() - { - _filter.setSigma((float)maskSize / 2.0f); - } - - /*! Returns the string "LocalAverageDepthF0D" */ - string getName() const - { - return "LocalAverageDepthF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class LocalAverageDepthF0D : public UnaryFunction0D<double> { + private: + GaussianFilter _filter; + + public: + /*! Builds the functor from the size of the mask that will be used. */ + LocalAverageDepthF0D(real maskSize = 5.0f) : UnaryFunction0D<double>() + { + _filter.setSigma((float)maskSize / 2.0f); + } + + /*! Returns the string "LocalAverageDepthF0D" */ + string getName() const + { + return "LocalAverageDepthF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // ReadMapPixel /*! Reads a pixel in a map. */ -class ReadMapPixelF0D : public UnaryFunction0D<float> -{ -private: - const char * _mapName; - int _level; - -public: - /*! Builds the functor from name of the - * Map that must be read. - * \param iMapName: - * The name of the map. - * \param level: - * The level of the pyramid from which the pixel must be read. - */ - ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>() - { - _mapName = iMapName; - _level = level; - } - - /*! Returns the string "ReadMapPixelF0D" */ - string getName() const - { - return "ReadMapPixelF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class ReadMapPixelF0D : public UnaryFunction0D<float> { + private: + const char *_mapName; + int _level; + + public: + /*! Builds the functor from name of the + * Map that must be read. + * \param iMapName: + * The name of the map. + * \param level: + * The level of the pyramid from which the pixel must be read. + */ + ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>() + { + _mapName = iMapName; + _level = level; + } + + /*! Returns the string "ReadMapPixelF0D" */ + string getName() const + { + return "ReadMapPixelF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // ReadSteerableViewMapPixel /*! Reads a pixel in one of the level of one of the steerable viewmaps. */ -class ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float> -{ -private: - unsigned _orientation; - int _level; - -public: - /*! Builds the functor - * \param nOrientation: - * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW) we are interested in. - * \param level: - * The level of the pyramid from which the pixel must be read. - */ - ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>() - { - _orientation = nOrientation; - _level = level; - } - - /*! Returns the string "ReadSteerableViewMapPixelF0D" */ - string getName() const - { - return "ReadSteerableViewMapPixelF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float> { + private: + unsigned _orientation; + int _level; + + public: + /*! Builds the functor + * \param nOrientation: + * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW) we are interested in. + * \param level: + * The level of the pyramid from which the pixel must be read. + */ + ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>() + { + _orientation = nOrientation; + _level = level; + } + + /*! Returns the string "ReadSteerableViewMapPixelF0D" */ + string getName() const + { + return "ReadSteerableViewMapPixelF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // ReadCompleteViewMapPixel /*! Reads a pixel in one of the level of the complete viewmap. */ -class ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float> -{ -private: - int _level; - -public: - /*! Builds the functor - * \param level: - * The level of the pyramid from which the pixel must be read. - */ - ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>() - { - _level = level; - } - - /*! Returns the string "ReadCompleteViewMapPixelF0D" */ - string getName() const - { - return "ReadCompleteViewMapPixelF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float> { + private: + int _level; + + public: + /*! Builds the functor + * \param level: + * The level of the pyramid from which the pixel must be read. + */ + ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>() + { + _level = level; + } + + /*! Returns the string "ReadCompleteViewMapPixelF0D" */ + string getName() const + { + return "ReadCompleteViewMapPixelF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // GetViewMapGradientNormF0D /*! Returns the norm of the gradient of the global viewmap density image. */ -class GetViewMapGradientNormF0D: public UnaryFunction0D< float> -{ -private: - int _level; - float _step; - -public: - /*! Builds the functor - * \param level: - * The level of the pyramid from which the pixel must be read. - */ - GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>() - { - _level = level; - _step = (float)pow(2.0, _level); - } - - /*! Returns the string "GetOccludeeF0D" */ - string getName() const - { - return "GetViewMapGradientNormF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class GetViewMapGradientNormF0D : public UnaryFunction0D<float> { + private: + int _level; + float _step; + + public: + /*! Builds the functor + * \param level: + * The level of the pyramid from which the pixel must be read. + */ + GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>() + { + _level = level; + _step = (float)pow(2.0, _level); + } + + /*! Returns the string "GetOccludeeF0D" */ + string getName() const + { + return "GetViewMapGradientNormF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; -} // end of namespace Functions0D +} // end of namespace Functions0D } /* namespace Freestyle */ -#endif // __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__ +#endif // __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__ diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp index 6d006dd395d..eadc8993dc6 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp @@ -29,100 +29,101 @@ namespace Freestyle { // FIXME namespace Functions1D { -int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) +int GetSteerableViewMapDensityF1D::operator()(Interface1D &inter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - Interface0DIterator it = inter.pointsBegin(_sampling); - Interface0DIterator itnext = it; - ++itnext; - FEdge *fe; - unsigned nSVM; - vector<float> values; + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + Interface0DIterator it = inter.pointsBegin(_sampling); + Interface0DIterator itnext = it; + ++itnext; + FEdge *fe; + unsigned nSVM; + vector<float> values; - while (!itnext.isEnd()) { - Interface0D& i0D = (*it); - Interface0D& i0Dnext = (*itnext); - fe = i0D.getFEdge(i0Dnext); - if (fe == 0) { - cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " << - i0Dnext.getId() << endl; - // compute the direction between these two ??? - Vec2f dir = i0Dnext.getPoint2D() - i0D.getPoint2D(); - nSVM = svm->getSVMNumber(dir); - } - else { - nSVM = svm->getSVMNumber(fe->getId().getFirst()); - } - Vec2r m((i0D.getProjectedX() + i0Dnext.getProjectedX()) / 2.0, - (i0D.getProjectedY() + i0Dnext.getProjectedY()) / 2.0); - values.push_back(svm->readSteerableViewMapPixel(nSVM, _level, (int)m[0], (int)m[1])); - ++it; - ++itnext; - } + while (!itnext.isEnd()) { + Interface0D &i0D = (*it); + Interface0D &i0Dnext = (*itnext); + fe = i0D.getFEdge(i0Dnext); + if (fe == 0) { + cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " + << i0Dnext.getId() << endl; + // compute the direction between these two ??? + Vec2f dir = i0Dnext.getPoint2D() - i0D.getPoint2D(); + nSVM = svm->getSVMNumber(dir); + } + else { + nSVM = svm->getSVMNumber(fe->getId().getFirst()); + } + Vec2r m((i0D.getProjectedX() + i0Dnext.getProjectedX()) / 2.0, + (i0D.getProjectedY() + i0Dnext.getProjectedY()) / 2.0); + values.push_back(svm->readSteerableViewMapPixel(nSVM, _level, (int)m[0], (int)m[1])); + ++it; + ++itnext; + } - float res, res_tmp; - vector<float>::iterator v = values.begin(), vend = values.end(); - unsigned size = 1; - switch (_integration) { - case MIN: - res = *v; - ++v; - for (; v != vend; ++v) { - res_tmp = *v; - if (res_tmp < res) - res = res_tmp; - } - break; - case MAX: - res = *v; - ++v; - for (; v != vend; ++v) { - res_tmp = *v; - if (res_tmp > res) - res = res_tmp; - } - break; - case FIRST: - res = *v; - break; - case LAST: - --vend; - res = *vend; - break; - case MEAN: - default: - res = *v; - ++v; - for (; v != vend; ++v, ++size) - res += *v; - res /= (size ? size : 1); - break; - } - result = res; - return 0; + float res, res_tmp; + vector<float>::iterator v = values.begin(), vend = values.end(); + unsigned size = 1; + switch (_integration) { + case MIN: + res = *v; + ++v; + for (; v != vend; ++v) { + res_tmp = *v; + if (res_tmp < res) + res = res_tmp; + } + break; + case MAX: + res = *v; + ++v; + for (; v != vend; ++v) { + res_tmp = *v; + if (res_tmp > res) + res = res_tmp; + } + break; + case FIRST: + res = *v; + break; + case LAST: + --vend; + res = *vend; + break; + case MEAN: + default: + res = *v; + ++v; + for (; v != vend; ++v, ++size) + res += *v; + res /= (size ? size : 1); + break; + } + result = res; + return 0; } -int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter) +int GetDirectionalViewMapDensityF1D::operator()(Interface1D &inter) { - //soc unsigned size; - result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; + //soc unsigned size; + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; } -int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) +int GetCompleteViewMapDensityF1D::operator()(Interface1D &inter) { - //soc unsigned size; - /* Id id = inter.getId(); */ /* UNUSED */ - result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; + //soc unsigned size; + /* Id id = inter.getId(); */ /* UNUSED */ + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; } -int GetViewMapGradientNormF1D::operator()(Interface1D& inter) +int GetViewMapGradientNormF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; + result = integrate( + _func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; } -} // Functions1D namespace +} // namespace Functions1D } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h index 6f5b2f34640..76a70d4f50d 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h @@ -40,46 +40,48 @@ namespace Functions1D { * The density is evaluated for a set of points along the Interface1D (using the DensityF0D functor) with a * user-defined sampling and then integrated into a single value using a user-defined integration method. */ -class DensityF1D : public UnaryFunction1D<double> -{ -private: - float _sampling; - -public: - /*! Builds the functor. - * \param sigma: - * Thesigma used in DensityF0D and determining the window size used in each density query. - * \param iType: - * The integration method used to compute a single value from a set of values. - * \param sampling: - * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and - * the result is obtained by combining the resulting values into a single one, following the method specified - * by iType. - */ - DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling = 2.0f) - : UnaryFunction1D<double>(iType), _fun(sigma) - { - _sampling = sampling; - } - - /*! Destructor */ - virtual ~DensityF1D() {} - - /*! Returns the string "DensityF1D"*/ - string getName() const - { - return "DensityF1D"; - } - - /*! the () operator.*/ - int operator()(Interface1D& inter) - { - result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; - } - -private: - Functions0D::DensityF0D _fun; +class DensityF1D : public UnaryFunction1D<double> { + private: + float _sampling; + + public: + /*! Builds the functor. + * \param sigma: + * Thesigma used in DensityF0D and determining the window size used in each density query. + * \param iType: + * The integration method used to compute a single value from a set of values. + * \param sampling: + * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and + * the result is obtained by combining the resulting values into a single one, following the method specified + * by iType. + */ + DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling = 2.0f) + : UnaryFunction1D<double>(iType), _fun(sigma) + { + _sampling = sampling; + } + + /*! Destructor */ + virtual ~DensityF1D() + { + } + + /*! Returns the string "DensityF1D"*/ + string getName() const + { + return "DensityF1D"; + } + + /*! the () operator.*/ + int operator()(Interface1D &inter) + { + result = integrate( + _fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; + } + + private: + Functions0D::DensityF0D _fun; }; // LocalAverageDepthF1D @@ -87,35 +89,34 @@ private: * The average depth is evaluated for a set of points along the Interface1D (using the LocalAverageDepthF0D functor) * with a user-defined sampling and then integrated into a single value using a user-defined integration method. */ -class LocalAverageDepthF1D : public UnaryFunction1D<double> -{ -public: - /*! Builds the functor. - * \param sigma: - * The sigma used in DensityF0D and determining the window size used in each density query. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN) - : UnaryFunction1D<double>(iType), _fun(sigma) - { - } - - /*! Returns the string "LocalAverageDepthF1D" */ - string getName() const - { - return "LocalAverageDepthF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter) - { - result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; - } - -private: - Functions0D::LocalAverageDepthF0D _fun; +class LocalAverageDepthF1D : public UnaryFunction1D<double> { + public: + /*! Builds the functor. + * \param sigma: + * The sigma used in DensityF0D and determining the window size used in each density query. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN) + : UnaryFunction1D<double>(iType), _fun(sigma) + { + } + + /*! Returns the string "LocalAverageDepthF1D" */ + string getName() const + { + return "LocalAverageDepthF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter) + { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + private: + Functions0D::LocalAverageDepthF0D _fun; }; // GetCompleteViewMapDensity @@ -123,40 +124,39 @@ private: * The density is evaluated for a set of points along the Interface1D (using the ReadCompleteViewMapPixelF0D functor) * and then integrated into a single value using a user-defined integration method. */ -class GetCompleteViewMapDensityF1D : public UnaryFunction1D<double> -{ -public: - /*! Builds the functor. - * \param level: - * The level of the pyramid from which - * the pixel must be read. - * \param iType: - * The integration method used to compute - * a single value from a set of values. - * \param sampling: - * The resolution used to sample the chain: the corresponding 0D function - * is evaluated at each sample point and the result is obtained by - * combining the resulting values into a single one, following the - * method specified by iType. - */ - GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling = 2.0f) - : UnaryFunction1D<double>(iType), _fun(level) - { - _sampling = sampling; - } - - /*! Returns the string "GetCompleteViewMapDensityF1D" */ - string getName() const - { - return "GetCompleteViewMapDensityF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); - -private: - Functions0D::ReadCompleteViewMapPixelF0D _fun; - float _sampling; +class GetCompleteViewMapDensityF1D : public UnaryFunction1D<double> { + public: + /*! Builds the functor. + * \param level: + * The level of the pyramid from which + * the pixel must be read. + * \param iType: + * The integration method used to compute + * a single value from a set of values. + * \param sampling: + * The resolution used to sample the chain: the corresponding 0D function + * is evaluated at each sample point and the result is obtained by + * combining the resulting values into a single one, following the + * method specified by iType. + */ + GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling = 2.0f) + : UnaryFunction1D<double>(iType), _fun(level) + { + _sampling = sampling; + } + + /*! Returns the string "GetCompleteViewMapDensityF1D" */ + string getName() const + { + return "GetCompleteViewMapDensityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); + + private: + Functions0D::ReadCompleteViewMapPixelF0D _fun; + float _sampling; }; // GetDirectionalViewMapDensity @@ -165,124 +165,125 @@ private: * The density is evaluated for a set of points along the Interface1D (using the ReadSteerableViewMapPixelF0D functor) * and then integrated into a single value using a user-defined integration method. */ -class GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double> -{ -public: - /*! Builds the functor. - * \param iOrientation: - * The number of the directional map we must work with. - * \param level: - * The level of the pyramid from which the pixel must be read. - * \param iType: - * The integration method used to compute a single value from a set of values. - * \param sampling: - * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and - * the result is obtained by combining the resulting values into a single one, following the method specified - * by iType. - */ - GetDirectionalViewMapDensityF1D(unsigned iOrientation, unsigned level, IntegrationType iType = MEAN, - float sampling = 2.0f) - : UnaryFunction1D<double>(iType), _fun(iOrientation, level) - { - _sampling = sampling; - } - - /*! Returns the string "GetDirectionalViewMapDensityF1D" */ - string getName() const - { - return "GetDirectionalViewMapDensityF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); - -private: - Functions0D::ReadSteerableViewMapPixelF0D _fun; - float _sampling; +class GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double> { + public: + /*! Builds the functor. + * \param iOrientation: + * The number of the directional map we must work with. + * \param level: + * The level of the pyramid from which the pixel must be read. + * \param iType: + * The integration method used to compute a single value from a set of values. + * \param sampling: + * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and + * the result is obtained by combining the resulting values into a single one, following the method specified + * by iType. + */ + GetDirectionalViewMapDensityF1D(unsigned iOrientation, + unsigned level, + IntegrationType iType = MEAN, + float sampling = 2.0f) + : UnaryFunction1D<double>(iType), _fun(iOrientation, level) + { + _sampling = sampling; + } + + /*! Returns the string "GetDirectionalViewMapDensityF1D" */ + string getName() const + { + return "GetDirectionalViewMapDensityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); + + private: + Functions0D::ReadSteerableViewMapPixelF0D _fun; + float _sampling; }; // GetSteerableViewMapDensityF1D /*! Returns the density of the viewmap for a given Interface1D. The density of each FEdge is evaluated * in the proper steerable ViewMap depending on its oorientation. */ -class GetSteerableViewMapDensityF1D : public UnaryFunction1D<double> -{ -private: - int _level; - float _sampling; - -public: - /*! Builds the functor from the level of the pyramid from which the pixel must be read. - * \param level: - * The level of the pyramid from which the pixel must be read. - * \param iType: - * The integration method used to compute a single value from a set of values. - * \param sampling: - * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and - * the result is obtained by combining the resulting values into a single one, following the method specified - * by iType. - */ - GetSteerableViewMapDensityF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f) - : UnaryFunction1D<double>(iType) - { - _level = level; - _sampling = sampling; - } - - /*! Destructor */ - virtual ~GetSteerableViewMapDensityF1D() {} - - /*! Returns the string "GetSteerableViewMapDensityF1D" */ - string getName() const - { - return "GetSteerableViewMapDensityF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetSteerableViewMapDensityF1D : public UnaryFunction1D<double> { + private: + int _level; + float _sampling; + + public: + /*! Builds the functor from the level of the pyramid from which the pixel must be read. + * \param level: + * The level of the pyramid from which the pixel must be read. + * \param iType: + * The integration method used to compute a single value from a set of values. + * \param sampling: + * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and + * the result is obtained by combining the resulting values into a single one, following the method specified + * by iType. + */ + GetSteerableViewMapDensityF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f) + : UnaryFunction1D<double>(iType) + { + _level = level; + _sampling = sampling; + } + + /*! Destructor */ + virtual ~GetSteerableViewMapDensityF1D() + { + } + + /*! Returns the string "GetSteerableViewMapDensityF1D" */ + string getName() const + { + return "GetSteerableViewMapDensityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetViewMapGradientNormF1D /*! Returns the density of the viewmap for a given Interface1D. The density of each FEdge is evaluated in * the proper steerable ViewMap depending on its oorientation. */ -class GetViewMapGradientNormF1D : public UnaryFunction1D<double> -{ -private: - int _level; - float _sampling; - Functions0D::GetViewMapGradientNormF0D _func; - -public: - /*! Builds the functor from the level of the pyramid from which the pixel must be read. - * \param level: - * The level of the pyramid from which the pixel must be read. - * \param iType: - * The integration method used to compute a single value from a set of values. - * \param sampling: - * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and - * the result is obtained by combining the resulting values into a single one, following the method specified - * by iType. - */ - GetViewMapGradientNormF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f) - : UnaryFunction1D<double>(iType), _func(level) - { - _level = level; - _sampling = sampling; - } - - /*! Returns the string "GetSteerableViewMapDensityF1D" */ - string getName() const - { - return "GetViewMapGradientNormF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetViewMapGradientNormF1D : public UnaryFunction1D<double> { + private: + int _level; + float _sampling; + Functions0D::GetViewMapGradientNormF0D _func; + + public: + /*! Builds the functor from the level of the pyramid from which the pixel must be read. + * \param level: + * The level of the pyramid from which the pixel must be read. + * \param iType: + * The integration method used to compute a single value from a set of values. + * \param sampling: + * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and + * the result is obtained by combining the resulting values into a single one, following the method specified + * by iType. + */ + GetViewMapGradientNormF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f) + : UnaryFunction1D<double>(iType), _func(level) + { + _level = level; + _sampling = sampling; + } + + /*! Returns the string "GetSteerableViewMapDensityF1D" */ + string getName() const + { + return "GetViewMapGradientNormF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; -} // end of namespace Functions1D +} // end of namespace Functions1D } /* namespace Freestyle */ -#endif // __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__ +#endif // __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__ diff --git a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h index e3bfae8289a..df66f82b868 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h @@ -42,45 +42,44 @@ namespace Predicates1D { /*! Returns true if the density evaluated for the * Interface1D is less than a user-defined density value. */ -class DensityLowerThanUP1D : public UnaryPredicate1D -{ -public: - /*! Builds the functor. - * \param threshold: - * The value of the threshold density. - * Any Interface1D having a density lower than this threshold will match. - * \param sigma: - * The sigma value defining the density evaluation window size used in the DensityF0D functor. - */ - DensityLowerThanUP1D(double threshold, double sigma = 2) - { - _threshold = threshold; - _sigma = sigma; - } +class DensityLowerThanUP1D : public UnaryPredicate1D { + public: + /*! Builds the functor. + * \param threshold: + * The value of the threshold density. + * Any Interface1D having a density lower than this threshold will match. + * \param sigma: + * The sigma value defining the density evaluation window size used in the DensityF0D functor. + */ + DensityLowerThanUP1D(double threshold, double sigma = 2) + { + _threshold = threshold; + _sigma = sigma; + } - /*! Returns the string "DensityLowerThanUP1D" */ - string getName() const - { - return "DensityLowerThanUP1D"; - } + /*! Returns the string "DensityLowerThanUP1D" */ + string getName() const + { + return "DensityLowerThanUP1D"; + } - /*! The () operator. */ - int operator()(Interface1D& inter) - { - Functions1D::DensityF1D fun(_sigma); - if (fun(inter) < 0) - return -1; - result = (fun.result < _threshold); - return 0; - } + /*! The () operator. */ + int operator()(Interface1D &inter) + { + Functions1D::DensityF1D fun(_sigma); + if (fun(inter) < 0) + return -1; + result = (fun.result < _threshold); + return 0; + } -private: - double _sigma; - double _threshold; + private: + double _sigma; + double _threshold; }; -} // end of namespace Predicates1D +} // end of namespace Predicates1D } /* namespace Freestyle */ -#endif // __FREESTYLE_ADVANCED_PREDICATES_1D_H__ +#endif // __FREESTYLE_ADVANCED_PREDICATES_1D_H__ diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp index 247fde9a9c0..a7883187066 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp @@ -33,46 +33,49 @@ namespace Freestyle { // ///////////////////////////////////////// -CalligraphicShader::CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp) -: StrokeShader() +CalligraphicShader::CalligraphicShader(real iMinThickness, + real iMaxThickness, + const Vec2f &iOrientation, + bool clamp) + : StrokeShader() { - _minThickness = iMinThickness; - _maxThickness = iMaxThickness; - _orientation = iOrientation; - _orientation.normalize(); - _clamp = clamp; + _minThickness = iMinThickness; + _maxThickness = iMaxThickness; + _orientation = iOrientation; + _orientation.normalize(); + _clamp = clamp; } int CalligraphicShader::shade(Stroke &ioStroke) const { - Interface0DIterator v; - Functions0D::VertexOrientation2DF0D fun; - StrokeVertex *sv; - for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) { - real thickness; - if (fun(v) < 0) - return -1; - - Vec2f vertexOri(fun.result); - Vec2r ori2d(-vertexOri[1], vertexOri[0]); - ori2d.normalizeSafe(); - real scal = ori2d * _orientation; - sv = dynamic_cast<StrokeVertex*>(&(*v)); - if (_clamp && (scal<0)) { - scal = 0.0; - sv->attribute().setColor(1, 1, 1); - } - else { - scal = fabs(scal); - sv->attribute().setColor(0, 0, 0); - } - thickness = _minThickness + scal * (_maxThickness - _minThickness); - if (thickness < 0.0) - thickness = 0.0; - sv->attribute().setThickness(thickness / 2.0, thickness / 2.0); - } - - return 0; + Interface0DIterator v; + Functions0D::VertexOrientation2DF0D fun; + StrokeVertex *sv; + for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) { + real thickness; + if (fun(v) < 0) + return -1; + + Vec2f vertexOri(fun.result); + Vec2r ori2d(-vertexOri[1], vertexOri[0]); + ori2d.normalizeSafe(); + real scal = ori2d * _orientation; + sv = dynamic_cast<StrokeVertex *>(&(*v)); + if (_clamp && (scal < 0)) { + scal = 0.0; + sv->attribute().setColor(1, 1, 1); + } + else { + scal = fabs(scal); + sv->attribute().setColor(0, 0, 0); + } + thickness = _minThickness + scal * (_maxThickness - _minThickness); + if (thickness < 0.0) + thickness = 0.0; + sv->attribute().setThickness(thickness / 2.0, thickness / 2.0); + } + + return 0; } ///////////////////////////////////////// @@ -83,64 +86,65 @@ int CalligraphicShader::shade(Stroke &ioStroke) const static const unsigned NB_VALUE_NOISE = 512; -SpatialNoiseShader::SpatialNoiseShader(float ioamount, float ixScale, int nbOctave, bool smooth, bool pureRandom) -: StrokeShader() +SpatialNoiseShader::SpatialNoiseShader( + float ioamount, float ixScale, int nbOctave, bool smooth, bool pureRandom) + : StrokeShader() { - _amount = ioamount; - if (ixScale == 0) - _xScale = 0; - else - _xScale = 1.0 / ixScale / real(NB_VALUE_NOISE); - _nbOctave = nbOctave; - _smooth = smooth; - _pureRandom = pureRandom; + _amount = ioamount; + if (ixScale == 0) + _xScale = 0; + else + _xScale = 1.0 / ixScale / real(NB_VALUE_NOISE); + _nbOctave = nbOctave; + _smooth = smooth; + _pureRandom = pureRandom; } int SpatialNoiseShader::shade(Stroke &ioStroke) const { - Interface0DIterator v, v2; - v = ioStroke.verticesBegin(); - Vec2r p(v->getProjectedX(), v->getProjectedY()); - v2 = v; - ++v2; - Vec2r p0(v2->getProjectedX(), v2->getProjectedY()); - p0 = p + 2 * (p - p0); - StrokeVertex *sv; - sv = dynamic_cast<StrokeVertex*>(&(*v)); - real initU = sv->strokeLength() * real(NB_VALUE_NOISE); - if (_pureRandom) - initU += RandGen::drand48() * real(NB_VALUE_NOISE); - - Functions0D::VertexOrientation2DF0D fun; - while (!v.isEnd()) { - sv = dynamic_cast<StrokeVertex*>(&(*v)); - Vec2r p(sv->getPoint()); - if (fun(v) < 0) - return -1; - Vec2r vertexOri(fun.result); - Vec2r ori2d(vertexOri[0], vertexOri[1]); - ori2d = Vec2r(p - p0); - ori2d.normalizeSafe(); - - PseudoNoise mynoise; - real bruit; - - if (_smooth) - bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave); - else - bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave); - - Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit); - - sv->setPoint(p[0] + noise[0], p[1] + noise[1]); - p0 = p; - - ++v; - } - - ioStroke.UpdateLength(); - - return 0; + Interface0DIterator v, v2; + v = ioStroke.verticesBegin(); + Vec2r p(v->getProjectedX(), v->getProjectedY()); + v2 = v; + ++v2; + Vec2r p0(v2->getProjectedX(), v2->getProjectedY()); + p0 = p + 2 * (p - p0); + StrokeVertex *sv; + sv = dynamic_cast<StrokeVertex *>(&(*v)); + real initU = sv->strokeLength() * real(NB_VALUE_NOISE); + if (_pureRandom) + initU += RandGen::drand48() * real(NB_VALUE_NOISE); + + Functions0D::VertexOrientation2DF0D fun; + while (!v.isEnd()) { + sv = dynamic_cast<StrokeVertex *>(&(*v)); + Vec2r p(sv->getPoint()); + if (fun(v) < 0) + return -1; + Vec2r vertexOri(fun.result); + Vec2r ori2d(vertexOri[0], vertexOri[1]); + ori2d = Vec2r(p - p0); + ori2d.normalizeSafe(); + + PseudoNoise mynoise; + real bruit; + + if (_smooth) + bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave); + else + bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave); + + Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit); + + sv->setPoint(p[0] + noise[0], p[1] + noise[1]); + p0 = p; + + ++v; + } + + ioStroke.UpdateLength(); + + return 0; } ///////////////////////////////////////// @@ -149,29 +153,40 @@ int SpatialNoiseShader::shade(Stroke &ioStroke) const // ///////////////////////////////////////// -SmoothingShader::SmoothingShader(int ionbIteration, real iFactorPoint, real ifactorCurvature, - real iFactorCurvatureDifference, real iAnisoPoint, real iAnisoNormal, - real iAnisoCurvature, real iCarricatureFactor) -: StrokeShader() +SmoothingShader::SmoothingShader(int ionbIteration, + real iFactorPoint, + real ifactorCurvature, + real iFactorCurvatureDifference, + real iAnisoPoint, + real iAnisoNormal, + real iAnisoCurvature, + real iCarricatureFactor) + : StrokeShader() { - _nbIterations = ionbIteration; - _factorCurvature = ifactorCurvature; - _factorCurvatureDifference = iFactorCurvatureDifference; - _anisoNormal = iAnisoNormal; - _anisoCurvature = iAnisoCurvature; - _carricatureFactor = iCarricatureFactor; - _factorPoint = iFactorPoint; - _anisoPoint = iAnisoPoint; + _nbIterations = ionbIteration; + _factorCurvature = ifactorCurvature; + _factorCurvatureDifference = iFactorCurvatureDifference; + _anisoNormal = iAnisoNormal; + _anisoCurvature = iAnisoCurvature; + _carricatureFactor = iCarricatureFactor; + _factorPoint = iFactorPoint; + _anisoPoint = iAnisoPoint; } int SmoothingShader::shade(Stroke &ioStroke) const { - // cerr << " Smoothing a stroke " << endl; - - Smoother smoother(ioStroke); - smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference, _anisoPoint, - _anisoNormal, _anisoCurvature, _carricatureFactor); - return 0; + // cerr << " Smoothing a stroke " << endl; + + Smoother smoother(ioStroke); + smoother.smooth(_nbIterations, + _factorPoint, + _factorCurvature, + _factorCurvatureDifference, + _anisoPoint, + _anisoNormal, + _anisoCurvature, + _carricatureFactor); + return 0; } // SMOOTHER @@ -179,152 +194,162 @@ int SmoothingShader::shade(Stroke &ioStroke) const Smoother::Smoother(Stroke &ioStroke) { - _stroke = &ioStroke; - - _nbVertices = ioStroke.vertices_size(); - _vertex = new Vec2r[_nbVertices]; - _curvature = new real[_nbVertices]; - _normal = new Vec2r[_nbVertices]; - StrokeInternal::StrokeVertexIterator v, vend; - int i = 0; - for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v, ++i) { - _vertex[i] = (v)->getPoint(); - } - Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]); - _isClosedCurve = (vec_tmp.norm() < M_EPSILON); - - _safeTest = (_nbVertices > 4); + _stroke = &ioStroke; + + _nbVertices = ioStroke.vertices_size(); + _vertex = new Vec2r[_nbVertices]; + _curvature = new real[_nbVertices]; + _normal = new Vec2r[_nbVertices]; + StrokeInternal::StrokeVertexIterator v, vend; + int i = 0; + for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; + ++v, ++i) { + _vertex[i] = (v)->getPoint(); + } + Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]); + _isClosedCurve = (vec_tmp.norm() < M_EPSILON); + + _safeTest = (_nbVertices > 4); } Smoother::~Smoother() { - delete[] _vertex; - delete[] _curvature; - delete[] _normal; + delete[] _vertex; + delete[] _curvature; + delete[] _normal; } -void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, - real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor) +void Smoother::smooth(int nbIteration, + real iFactorPoint, + real ifactorCurvature, + real iFactorCurvatureDifference, + real iAnisoPoint, + real iAnisoNormal, + real iAnisoCurvature, + real iCarricatureFactor) { - _factorCurvature = ifactorCurvature; - _factorCurvatureDifference = iFactorCurvatureDifference; - _anisoNormal = iAnisoNormal; - _anisoCurvature = iAnisoCurvature; - _carricatureFactor = iCarricatureFactor; - _factorPoint = iFactorPoint; - _anisoPoint = iAnisoPoint; - - for (int i = 0; i < nbIteration; ++i) - iteration (); - copyVertices(); + _factorCurvature = ifactorCurvature; + _factorCurvatureDifference = iFactorCurvatureDifference; + _anisoNormal = iAnisoNormal; + _anisoCurvature = iAnisoCurvature; + _carricatureFactor = iCarricatureFactor; + _factorPoint = iFactorPoint; + _anisoPoint = iAnisoPoint; + + for (int i = 0; i < nbIteration; ++i) + iteration(); + copyVertices(); } static real edgeStopping(real x, real sigma) { - if (sigma == 0.0) - return 1.0; - return exp(-x * x / (sigma * sigma)); + if (sigma == 0.0) + return 1.0; + return exp(-x * x / (sigma * sigma)); } void Smoother::iteration() { - computeCurvature(); - for (int i = 1; i < (_nbVertices - 1); ++i) { - real motionNormal = _factorCurvature * _curvature[i] * edgeStopping(_curvature[i], _anisoNormal); - - real diffC1 = _curvature[i] - _curvature[i - 1]; - real diffC2 = _curvature[i] - _curvature[i + 1]; - real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 + - edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference; - motionCurvature *= _factorCurvatureDifference; - //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2); - if (_safeTest) - _vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]); - Vec2r v1(_vertex[i - 1] - _vertex[i]); - Vec2r v2(_vertex[i + 1] - _vertex[i]); - real d1 = v1.norm(); - real d2 = v2.norm(); - _vertex[i] = Vec2r(_vertex[i] + - _factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) + - _factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i])); - } - - if (_isClosedCurve) { - real motionNormal = _factorCurvature * _curvature[0] * edgeStopping(_curvature[0], _anisoNormal); - - real diffC1 = _curvature[0] - _curvature[_nbVertices - 2]; - real diffC2 = _curvature[0] - _curvature[1]; - real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 + - edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference; - motionCurvature *= _factorCurvatureDifference; - //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2); - _vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]); - _vertex[_nbVertices - 1] = _vertex[0]; - } + computeCurvature(); + for (int i = 1; i < (_nbVertices - 1); ++i) { + real motionNormal = _factorCurvature * _curvature[i] * + edgeStopping(_curvature[i], _anisoNormal); + + real diffC1 = _curvature[i] - _curvature[i - 1]; + real diffC2 = _curvature[i] - _curvature[i + 1]; + real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 + + edgeStopping(diffC2, _anisoCurvature) * + diffC2; //_factorCurvatureDifference; + motionCurvature *= _factorCurvatureDifference; + //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2); + if (_safeTest) + _vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]); + Vec2r v1(_vertex[i - 1] - _vertex[i]); + Vec2r v2(_vertex[i + 1] - _vertex[i]); + real d1 = v1.norm(); + real d2 = v2.norm(); + _vertex[i] = Vec2r( + _vertex[i] + _factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) + + _factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i])); + } + + if (_isClosedCurve) { + real motionNormal = _factorCurvature * _curvature[0] * + edgeStopping(_curvature[0], _anisoNormal); + + real diffC1 = _curvature[0] - _curvature[_nbVertices - 2]; + real diffC2 = _curvature[0] - _curvature[1]; + real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 + + edgeStopping(diffC2, _anisoCurvature) * + diffC2; //_factorCurvatureDifference; + motionCurvature *= _factorCurvatureDifference; + //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2); + _vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]); + _vertex[_nbVertices - 1] = _vertex[0]; + } } - void Smoother::computeCurvature() { - int i; - Vec2r BA, BC, normalCurvature; - for (i = 1; i < (_nbVertices - 1); ++i) { - BA = _vertex[i - 1] - _vertex[i]; - BC = _vertex[i + 1] - _vertex[i]; - real lba = BA.norm(), lbc = BC.norm(); - BA.normalizeSafe(); - BC.normalizeSafe(); - normalCurvature = BA + BC; - - _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]); - _normal[i].normalizeSafe(); - - _curvature[i] = normalCurvature * _normal[i]; - if (lba + lbc > M_EPSILON) - _curvature[i] /= (0.5 * lba + lbc); - } - _curvature[0] = _curvature[1]; - _curvature[_nbVertices - 1] = _curvature[_nbVertices - 2]; - Vec2r di(_vertex[1] - _vertex[0]); - _normal[0] = Vec2r(-di[1], di[0]); - _normal[0].normalizeSafe(); - di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2]; - _normal[_nbVertices - 1] = Vec2r(-di[1], di[0]); - _normal[_nbVertices - 1].normalizeSafe(); - - if (_isClosedCurve) { - BA = _vertex[_nbVertices - 2] - _vertex[0]; - BC = _vertex[1] - _vertex[0]; - real lba = BA.norm(), lbc = BC.norm(); - BA.normalizeSafe(); - BC.normalizeSafe(); - normalCurvature = BA + BC; - - _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]); - _normal[i].normalizeSafe(); - - _curvature[i] = normalCurvature * _normal[i]; - if (lba + lbc > M_EPSILON) - _curvature[i] /= (0.5 * lba + lbc); - - _normal[_nbVertices - 1] = _normal[0]; - _curvature[_nbVertices - 1] = _curvature[0]; - } + int i; + Vec2r BA, BC, normalCurvature; + for (i = 1; i < (_nbVertices - 1); ++i) { + BA = _vertex[i - 1] - _vertex[i]; + BC = _vertex[i + 1] - _vertex[i]; + real lba = BA.norm(), lbc = BC.norm(); + BA.normalizeSafe(); + BC.normalizeSafe(); + normalCurvature = BA + BC; + + _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]); + _normal[i].normalizeSafe(); + + _curvature[i] = normalCurvature * _normal[i]; + if (lba + lbc > M_EPSILON) + _curvature[i] /= (0.5 * lba + lbc); + } + _curvature[0] = _curvature[1]; + _curvature[_nbVertices - 1] = _curvature[_nbVertices - 2]; + Vec2r di(_vertex[1] - _vertex[0]); + _normal[0] = Vec2r(-di[1], di[0]); + _normal[0].normalizeSafe(); + di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2]; + _normal[_nbVertices - 1] = Vec2r(-di[1], di[0]); + _normal[_nbVertices - 1].normalizeSafe(); + + if (_isClosedCurve) { + BA = _vertex[_nbVertices - 2] - _vertex[0]; + BC = _vertex[1] - _vertex[0]; + real lba = BA.norm(), lbc = BC.norm(); + BA.normalizeSafe(); + BC.normalizeSafe(); + normalCurvature = BA + BC; + + _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]); + _normal[i].normalizeSafe(); + + _curvature[i] = normalCurvature * _normal[i]; + if (lba + lbc > M_EPSILON) + _curvature[i] /= (0.5 * lba + lbc); + + _normal[_nbVertices - 1] = _normal[0]; + _curvature[_nbVertices - 1] = _curvature[0]; + } } void Smoother::copyVertices() { - int i = 0; - StrokeInternal::StrokeVertexIterator v, vend; - for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) { - const Vec2r p0((v)->getPoint()); - const Vec2r p1(_vertex[i]); - Vec2r p(p0 + _carricatureFactor * (p1 - p0)); - - (v)->setPoint(p[0], p[1]); - ++i; - } - _stroke->UpdateLength(); + int i = 0; + StrokeInternal::StrokeVertexIterator v, vend; + for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) { + const Vec2r p0((v)->getPoint()); + const Vec2r p1(_vertex[i]); + Vec2r p(p0 + _carricatureFactor * (p1 - p0)); + + (v)->setPoint(p[0], p[1]); + ++i; + } + _stroke->UpdateLength(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h index 0e14e4f3631..17b180531a2 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h @@ -31,32 +31,36 @@ namespace Freestyle { * i.e. The stroke will be the thickest in a main direction, the thinest in the direction perpendicular to this one, * and an interpolation inbetween. */ -class CalligraphicShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param iMinThickness: - * The minimum thickness in the direction perpandicular to the main direction. - * \param iMaxThickness: - * The maximum thickness in the main direction. - * \param iOrientation: - * The 2D vector giving the main direction. - * \param clamp: - * Tells ??? - */ - CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp); - - /*! Destructor. */ - virtual ~CalligraphicShader() {} - - /*! The shading method */ - virtual int shade(Stroke &ioStroke) const; - -protected: - real _maxThickness; - real _minThickness; - Vec2f _orientation; - bool _clamp; +class CalligraphicShader : public StrokeShader { + public: + /*! Builds the shader. + * \param iMinThickness: + * The minimum thickness in the direction perpandicular to the main direction. + * \param iMaxThickness: + * The maximum thickness in the main direction. + * \param iOrientation: + * The 2D vector giving the main direction. + * \param clamp: + * Tells ??? + */ + CalligraphicShader(real iMinThickness, + real iMaxThickness, + const Vec2f &iOrientation, + bool clamp); + + /*! Destructor. */ + virtual ~CalligraphicShader() + { + } + + /*! The shading method */ + virtual int shade(Stroke &ioStroke) const; + + protected: + real _maxThickness; + real _minThickness; + Vec2f _orientation; + bool _clamp; }; /*! [ Geometry Shader ]. @@ -64,35 +68,36 @@ protected: * Moves the vertices to make the stroke more noisy. * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a> \endhtmlonly */ -class SpatialNoiseShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param iAmount: - * The amplitude of the noise. - * \param ixScale: - * The noise frequency - * \param nbOctave: - * The number of octaves - * \param smooth: - * If you want the noise to be smooth - * \param pureRandom: - * If you don't want any coherence - */ - SpatialNoiseShader(float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom); - - /*! Destructor. */ - virtual ~SpatialNoiseShader() {} - - /*! The shading method. */ - virtual int shade(Stroke &ioStroke) const; - -protected: - float _amount; - float _xScale; - int _nbOctave; - bool _smooth; - bool _pureRandom; +class SpatialNoiseShader : public StrokeShader { + public: + /*! Builds the shader. + * \param iAmount: + * The amplitude of the noise. + * \param ixScale: + * The noise frequency + * \param nbOctave: + * The number of octaves + * \param smooth: + * If you want the noise to be smooth + * \param pureRandom: + * If you don't want any coherence + */ + SpatialNoiseShader(float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom); + + /*! Destructor. */ + virtual ~SpatialNoiseShader() + { + } + + /*! The shading method. */ + virtual int shade(Stroke &ioStroke) const; + + protected: + float _amount; + float _xScale; + int _nbOctave; + bool _smooth; + bool _pureRandom; }; /*! [ Geometry Shader ]. @@ -102,116 +107,130 @@ protected: * to prevent the diffusion accross corners. * \see \htmlonly <a href=/smoothing/smoothing.html>smoothing/smoothing.html</a> \endhtmlonly */ -class SmoothingShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param iNbIteration: - * The number of iterations. (400) - * \param iFactorPoint: - * 0 - * \param ifactorCurvature: - * 0 - * \param iFactorCurvatureDifference: - * 0.2 - * \param iAnisoPoint: - * 0 - * \param iAnisNormal: - * 0 - * \param iAnisoCurvature: - * 0 - * \param icarricatureFactor: - * 1 - */ - SmoothingShader(int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, - real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor); - - /*! Destructor. */ - virtual ~SmoothingShader() {} - - /*! The shading method. */ - virtual int shade(Stroke &ioStroke) const; - -protected: - int _nbIterations; - real _factorPoint; - real _factorCurvature; - real _factorCurvatureDifference; - real _anisoPoint; - real _anisoNormal; - real _anisoCurvature; - real _carricatureFactor; +class SmoothingShader : public StrokeShader { + public: + /*! Builds the shader. + * \param iNbIteration: + * The number of iterations. (400) + * \param iFactorPoint: + * 0 + * \param ifactorCurvature: + * 0 + * \param iFactorCurvatureDifference: + * 0.2 + * \param iAnisoPoint: + * 0 + * \param iAnisNormal: + * 0 + * \param iAnisoCurvature: + * 0 + * \param icarricatureFactor: + * 1 + */ + SmoothingShader(int iNbIteration, + real iFactorPoint, + real ifactorCurvature, + real iFactorCurvatureDifference, + real iAnisoPoint, + real iAnisoNormal, + real iAnisoCurvature, + real icarricatureFactor); + + /*! Destructor. */ + virtual ~SmoothingShader() + { + } + + /*! The shading method. */ + virtual int shade(Stroke &ioStroke) const; + + protected: + int _nbIterations; + real _factorPoint; + real _factorCurvature; + real _factorCurvatureDifference; + real _anisoPoint; + real _anisoNormal; + real _anisoCurvature; + real _carricatureFactor; }; -class Smoother -{ -public: - Smoother(Stroke &ioStroke); - - virtual ~Smoother(); - - void smooth(int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, - real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor); - - void computeCurvature(); - -protected: - real _factorPoint; - real _factorCurvature; - real _factorCurvatureDifference; - real _anisoPoint; - real _anisoNormal; - real _anisoCurvature; - real _carricatureFactor; - - void iteration(); - void copyVertices (); - - Stroke *_stroke; - int _nbVertices; - Vec2r *_vertex; - Vec2r *_normal; - real *_curvature; - bool *_isFixedVertex; - - bool _isClosedCurve; - bool _safeTest; +class Smoother { + public: + Smoother(Stroke &ioStroke); + + virtual ~Smoother(); + + void smooth(int nbIterations, + real iFactorPoint, + real ifactorCurvature, + real iFactorCurvatureDifference, + real iAnisoPoint, + real iAnisoNormal, + real iAnisoCurvature, + real icarricatureFactor); + + void computeCurvature(); + + protected: + real _factorPoint; + real _factorCurvature; + real _factorCurvatureDifference; + real _anisoPoint; + real _anisoNormal; + real _anisoCurvature; + real _carricatureFactor; + + void iteration(); + void copyVertices(); + + Stroke *_stroke; + int _nbVertices; + Vec2r *_vertex; + Vec2r *_normal; + real *_curvature; + bool *_isFixedVertex; + + bool _isClosedCurve; + bool _safeTest; }; -class Omitter : public Smoother -{ -public: - Omitter(Stroke &ioStroke); +class Omitter : public Smoother { + public: + Omitter(Stroke &ioStroke); - virtual ~Omitter() {} + virtual ~Omitter() + { + } - void omit(real sizeWindow, real thrVari, real thrFlat, real lFlat); + void omit(real sizeWindow, real thrVari, real thrFlat, real lFlat); -protected: - real *_u; + protected: + real *_u; - real _sizeWindow; - real _thresholdVariation; - real _thresholdFlat; - real _lengthFlat; + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; }; /*! Omission shader */ -class OmissionShader : public StrokeShader -{ -public: - OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat); - virtual ~OmissionShader() {} - - virtual int shade(Stroke &ioStroke) const; - -protected: - real _sizeWindow; - real _thresholdVariation; - real _thresholdFlat; - real _lengthFlat; +class OmissionShader : public StrokeShader { + public: + OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat); + virtual ~OmissionShader() + { + } + + virtual int shade(Stroke &ioStroke) const; + + protected: + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_ADVANCED_STROKE_SHADERS_H__ +#endif // __FREESTYLE_ADVANCED_STROKE_SHADERS_H__ diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp index 0a925949617..15541c1f438 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -38,8 +38,8 @@ #include "BKE_global.h" extern "C" { -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } namespace Freestyle { @@ -51,143 +51,142 @@ namespace StrokeShaders { // ////////////////////////////////////////////////////////// -int ConstantThicknessShader::shade(Stroke& stroke) const +int ConstantThicknessShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v, vend; - int i = 0; - int size = stroke.strokeVerticesSize(); - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? - if ((1 == i) || (size - 2 == i)) - v->attribute().setThickness(_thickness / 4.0, _thickness / 4.0); - if ((0 == i) || (size - 1 == i)) - v->attribute().setThickness(0, 0); - - v->attribute().setThickness(_thickness / 2.0, _thickness / 2.0); - } - return 0; + StrokeInternal::StrokeVertexIterator v, vend; + int i = 0; + int size = stroke.strokeVerticesSize(); + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? + if ((1 == i) || (size - 2 == i)) + v->attribute().setThickness(_thickness / 4.0, _thickness / 4.0); + if ((0 == i) || (size - 1 == i)) + v->attribute().setThickness(0, 0); + + v->attribute().setThickness(_thickness / 2.0, _thickness / 2.0); + } + return 0; } -int ConstantExternThicknessShader::shade(Stroke& stroke) const +int ConstantExternThicknessShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v, vend; - int i = 0; - int size = stroke.strokeVerticesSize(); - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? - if ((1 == i) || (size - 2 == i)) - v->attribute().setThickness(_thickness / 2.0, 0); - if ((0 == i) || (size - 1 == i)) - v->attribute().setThickness(0, 0); - - v->attribute().setThickness(_thickness, 0); - } - return 0; + StrokeInternal::StrokeVertexIterator v, vend; + int i = 0; + int size = stroke.strokeVerticesSize(); + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? + if ((1 == i) || (size - 2 == i)) + v->attribute().setThickness(_thickness / 2.0, 0); + if ((0 == i) || (size - 1 == i)) + v->attribute().setThickness(0, 0); + + v->attribute().setThickness(_thickness, 0); + } + return 0; } -int IncreasingThicknessShader::shade(Stroke& stroke) const +int IncreasingThicknessShader::shade(Stroke &stroke) const { - int n = stroke.strokeVerticesSize() - 1, i; - StrokeInternal::StrokeVertexIterator v, vend; - for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); - v != vend; - ++v, ++i) - { - float t; - if (i < (float)n / 2.0f) - t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * _ThicknessMax; - else - t = (1.0 - (float)i / (float)n) * _ThicknessMax + (float)i / (float)n * _ThicknessMin; - v->attribute().setThickness(t / 2.0, t / 2.0); - } - return 0; + int n = stroke.strokeVerticesSize() - 1, i; + StrokeInternal::StrokeVertexIterator v, vend; + for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; + ++v, ++i) { + float t; + if (i < (float)n / 2.0f) + t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * _ThicknessMax; + else + t = (1.0 - (float)i / (float)n) * _ThicknessMax + (float)i / (float)n * _ThicknessMin; + v->attribute().setThickness(t / 2.0, t / 2.0); + } + return 0; } -int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const +int ConstrainedIncreasingThicknessShader::shade(Stroke &stroke) const { - float slength = stroke.getLength2D(); - float maxT = min(_ratio * slength, _ThicknessMax); - int n = stroke.strokeVerticesSize() - 1, i; - StrokeInternal::StrokeVertexIterator v, vend; - for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); - v != vend; - ++v, ++i) - { - // XXX Why not using an if/else here? Else, if last condition is true, everything else is computed for nothing! - float t; - if (i < (float)n / 2.0f) - t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * maxT; - else - t = (1.0 - (float)i / (float)n) * maxT + (float)i / (float)n * _ThicknessMin; - v->attribute().setThickness(t / 2.0, t / 2.0); - if (i == n - 1) - v->attribute().setThickness(_ThicknessMin / 2.0, _ThicknessMin / 2.0); - } - return 0; + float slength = stroke.getLength2D(); + float maxT = min(_ratio * slength, _ThicknessMax); + int n = stroke.strokeVerticesSize() - 1, i; + StrokeInternal::StrokeVertexIterator v, vend; + for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; + ++v, ++i) { + // XXX Why not using an if/else here? Else, if last condition is true, everything else is computed for nothing! + float t; + if (i < (float)n / 2.0f) + t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * maxT; + else + t = (1.0 - (float)i / (float)n) * maxT + (float)i / (float)n * _ThicknessMin; + v->attribute().setThickness(t / 2.0, t / 2.0); + if (i == n - 1) + v->attribute().setThickness(_ThicknessMin / 2.0, _ThicknessMin / 2.0); + } + return 0; } - -int LengthDependingThicknessShader::shade(Stroke& stroke) const +int LengthDependingThicknessShader::shade(Stroke &stroke) const { - float step = (_maxThickness - _minThickness) / 3.0f; - float l = stroke.getLength2D(); - float thickness = 0.0f; - if (l > 300.0f) - thickness = _minThickness + 3.0f * step; - else if ((l < 300.0f) && (l > 100.0f)) - thickness = _minThickness + 2.0f * step; - else if ((l < 100.0f) && (l > 50.0f)) - thickness = _minThickness + 1.0f * step; - else // else if (l < 50.0f), tsst... - thickness = _minThickness; - - StrokeInternal::StrokeVertexIterator v, vend; - int i = 0; - int size = stroke.strokeVerticesSize(); - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? - if ((1 == i) || (size - 2 == i)) - v->attribute().setThickness(thickness / 4.0, thickness / 4.0); - if ((0 == i) || (size - 1 == i)) - v->attribute().setThickness(0, 0); - - v->attribute().setThickness(thickness / 2.0, thickness / 2.0); - } - return 0; + float step = (_maxThickness - _minThickness) / 3.0f; + float l = stroke.getLength2D(); + float thickness = 0.0f; + if (l > 300.0f) + thickness = _minThickness + 3.0f * step; + else if ((l < 300.0f) && (l > 100.0f)) + thickness = _minThickness + 2.0f * step; + else if ((l < 100.0f) && (l > 50.0f)) + thickness = _minThickness + 1.0f * step; + else // else if (l < 50.0f), tsst... + thickness = _minThickness; + + StrokeInternal::StrokeVertexIterator v, vend; + int i = 0; + int size = stroke.strokeVerticesSize(); + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop? + if ((1 == i) || (size - 2 == i)) + v->attribute().setThickness(thickness / 4.0, thickness / 4.0); + if ((0 == i) || (size - 1 == i)) + v->attribute().setThickness(0, 0); + + v->attribute().setThickness(thickness / 2.0, thickness / 2.0); + } + return 0; } static const unsigned NB_VALUE_NOISE = 512; ThicknessNoiseShader::ThicknessNoiseShader() : StrokeShader() { - _amplitude = 1.0f; - _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE; + _amplitude = 1.0f; + _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE; } ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod) : StrokeShader() { - _amplitude = iAmplitude; - _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE; + _amplitude = iAmplitude; + _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE; } -int ThicknessNoiseShader::shade(Stroke& stroke) const +int ThicknessNoiseShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; - real initU1 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE); - real initU2 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE); - - real bruit, bruit2; - PseudoNoise mynoise, mynoise2; - for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves - bruit2 = mynoise2.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU2, 2); // 2 : nbOctaves - const float *originalThickness = v->attribute().getThickness(); - float r = bruit * _amplitude + originalThickness[0]; - float l = bruit2 * _amplitude + originalThickness[1]; - v->attribute().setThickness(r, l); - } - - return 0; + StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; + real initU1 = v->strokeLength() * real(NB_VALUE_NOISE) + + RandGen::drand48() * real(NB_VALUE_NOISE); + real initU2 = v->strokeLength() * real(NB_VALUE_NOISE) + + RandGen::drand48() * real(NB_VALUE_NOISE); + + real bruit, bruit2; + PseudoNoise mynoise, mynoise2; + for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, + 2); // 2 : nbOctaves + bruit2 = mynoise2.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU2, + 2); // 2 : nbOctaves + const float *originalThickness = v->attribute().getThickness(); + float r = bruit * _amplitude + originalThickness[0]; + float l = bruit2 * _amplitude + originalThickness[1]; + v->attribute().setThickness(r, l); + } + + return 0; } // @@ -195,78 +194,80 @@ int ThicknessNoiseShader::shade(Stroke& stroke) const // /////////////////////////////////////////////////////////////////////////////// -int ConstantColorShader::shade(Stroke& stroke) const +int ConstantColorShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v, vend; - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - v->attribute().setColor(_color[0], _color[1], _color[2]); - v->attribute().setAlpha(_color[3]); - } - return 0; + StrokeInternal::StrokeVertexIterator v, vend; + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + v->attribute().setColor(_color[0], _color[1], _color[2]); + v->attribute().setAlpha(_color[3]); + } + return 0; } -int IncreasingColorShader::shade(Stroke& stroke) const +int IncreasingColorShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v, vend; - int n = stroke.strokeVerticesSize() - 1, yo; - float newcolor[4]; - for (yo = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); - v != vend; - ++v, ++yo) - { - for (int i = 0; i < 4; ++i) { - newcolor[i] = (1.0 - (float) yo / (float)n) * _colorMin[i] + (float)yo / (float)n * _colorMax[i]; - } - v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]); - v->attribute().setAlpha(newcolor[3]); - } - return 0; + StrokeInternal::StrokeVertexIterator v, vend; + int n = stroke.strokeVerticesSize() - 1, yo; + float newcolor[4]; + for (yo = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; + ++v, ++yo) { + for (int i = 0; i < 4; ++i) { + newcolor[i] = (1.0 - (float)yo / (float)n) * _colorMin[i] + + (float)yo / (float)n * _colorMax[i]; + } + v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]); + v->attribute().setAlpha(newcolor[3]); + } + return 0; } -int MaterialColorShader::shade(Stroke& stroke) const +int MaterialColorShader::shade(Stroke &stroke) const { - Interface0DIterator v, vend; - Functions0D::MaterialF0D fun; - StrokeVertex *sv; - for (v = stroke.verticesBegin(), vend = stroke.verticesEnd(); v != vend; ++v) { - if (fun(v) < 0) - return -1; - const float *diffuse = fun.result.diffuse(); - sv = dynamic_cast<StrokeVertex*>(&(*v)); - sv->attribute().setColor(diffuse[0] * _coefficient, diffuse[1] * _coefficient, diffuse[2] * _coefficient); - sv->attribute().setAlpha(diffuse[3]); - } - return 0; + Interface0DIterator v, vend; + Functions0D::MaterialF0D fun; + StrokeVertex *sv; + for (v = stroke.verticesBegin(), vend = stroke.verticesEnd(); v != vend; ++v) { + if (fun(v) < 0) + return -1; + const float *diffuse = fun.result.diffuse(); + sv = dynamic_cast<StrokeVertex *>(&(*v)); + sv->attribute().setColor( + diffuse[0] * _coefficient, diffuse[1] * _coefficient, diffuse[2] * _coefficient); + sv->attribute().setAlpha(diffuse[3]); + } + return 0; } ColorNoiseShader::ColorNoiseShader() : StrokeShader() { - _amplitude = 1.0f; - _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE; + _amplitude = 1.0f; + _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE; } ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod) : StrokeShader() { - _amplitude = iAmplitude; - _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE; + _amplitude = iAmplitude; + _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE; } -int ColorNoiseShader::shade(Stroke& stroke) const +int ColorNoiseShader::shade(Stroke &stroke) const { - StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; - real initU = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE); - - real bruit; - PseudoNoise mynoise; - for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU, 2); // 2 : nbOctaves - const float *originalColor = v->attribute().getColor(); - float r = bruit * _amplitude + originalColor[0]; - float g = bruit * _amplitude + originalColor[1]; - float b = bruit * _amplitude + originalColor[2]; - v->attribute().setColor(r, g, b); - } - return 0; + StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; + real initU = v->strokeLength() * real(NB_VALUE_NOISE) + + RandGen::drand48() * real(NB_VALUE_NOISE); + + real bruit; + PseudoNoise mynoise; + for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU, + 2); // 2 : nbOctaves + const float *originalColor = v->attribute().getColor(); + float r = bruit * _amplitude + originalColor[0]; + float g = bruit * _amplitude + originalColor[1]; + float b = bruit * _amplitude + originalColor[2]; + v->attribute().setColor(r, g, b); + } + return 0; } // @@ -274,21 +275,21 @@ int ColorNoiseShader::shade(Stroke& stroke) const // /////////////////////////////////////////////////////////////////////////////// -int BlenderTextureShader::shade(Stroke& stroke) const +int BlenderTextureShader::shade(Stroke &stroke) const { - if (_mtex) - return stroke.setMTex(_mtex); - if (_nodeTree) { - stroke.setNodeTree(_nodeTree); - return 0; - } - return -1; + if (_mtex) + return stroke.setMTex(_mtex); + if (_nodeTree) { + stroke.setNodeTree(_nodeTree); + return 0; + } + return -1; } -int StrokeTextureStepShader::shade(Stroke& stroke) const +int StrokeTextureStepShader::shade(Stroke &stroke) const { - stroke.setTextureStep(_step); - return 0; + stroke.setTextureStep(_step); + return 0; } // @@ -296,319 +297,320 @@ int StrokeTextureStepShader::shade(Stroke& stroke) const // /////////////////////////////////////////////////////////////////////////////// -int BackboneStretcherShader::shade(Stroke& stroke) const +int BackboneStretcherShader::shade(Stroke &stroke) const { - float l = stroke.getLength2D(); - if (l <= 1.0e-6) - return 0; - - StrokeInternal::StrokeVertexIterator v0 = stroke.strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator v1 = v0; - ++v1; - StrokeInternal::StrokeVertexIterator vn = stroke.strokeVerticesEnd(); - --vn; - StrokeInternal::StrokeVertexIterator vn_1 = vn; - --vn_1; - - - Vec2d first((v0)->x(), (v0)->y()); - Vec2d last((vn)->x(), (vn)->y()); - - Vec2d d1(first - Vec2d((v1)->x(), (v1)->y())); - d1.normalize(); - Vec2d dn(last - Vec2d((vn_1)->x(), (vn_1)->y())); - dn.normalize(); - - Vec2d newFirst(first + _amount * d1); - (v0)->setPoint(newFirst[0], newFirst[1]); - Vec2d newLast(last + _amount * dn); - (vn)->setPoint(newLast[0], newLast[1]); - - stroke.UpdateLength(); - return 0; + float l = stroke.getLength2D(); + if (l <= 1.0e-6) + return 0; + + StrokeInternal::StrokeVertexIterator v0 = stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator v1 = v0; + ++v1; + StrokeInternal::StrokeVertexIterator vn = stroke.strokeVerticesEnd(); + --vn; + StrokeInternal::StrokeVertexIterator vn_1 = vn; + --vn_1; + + Vec2d first((v0)->x(), (v0)->y()); + Vec2d last((vn)->x(), (vn)->y()); + + Vec2d d1(first - Vec2d((v1)->x(), (v1)->y())); + d1.normalize(); + Vec2d dn(last - Vec2d((vn_1)->x(), (vn_1)->y())); + dn.normalize(); + + Vec2d newFirst(first + _amount * d1); + (v0)->setPoint(newFirst[0], newFirst[1]); + Vec2d newLast(last + _amount * dn); + (vn)->setPoint(newLast[0], newLast[1]); + + stroke.UpdateLength(); + return 0; } -int SamplingShader::shade(Stroke& stroke) const +int SamplingShader::shade(Stroke &stroke) const { - stroke.Resample(_sampling); - stroke.UpdateLength(); - return 0; + stroke.Resample(_sampling); + stroke.UpdateLength(); + return 0; } -int ExternalContourStretcherShader::shade(Stroke& stroke) const +int ExternalContourStretcherShader::shade(Stroke &stroke) const { - //float l = stroke.getLength2D(); - Interface0DIterator it; - Functions0D::Normal2DF0D fun; - StrokeVertex *sv; - for (it = stroke.verticesBegin(); !it.isEnd(); ++it) { - if (fun(it) < 0) - return -1; - Vec2f n(fun.result); - sv = dynamic_cast<StrokeVertex*>(&(*it)); - Vec2d newPoint(sv->x() + _amount * n.x(), sv->y() + _amount * n.y()); - sv->setPoint(newPoint[0], newPoint[1]); - } - stroke.UpdateLength(); - return 0; + //float l = stroke.getLength2D(); + Interface0DIterator it; + Functions0D::Normal2DF0D fun; + StrokeVertex *sv; + for (it = stroke.verticesBegin(); !it.isEnd(); ++it) { + if (fun(it) < 0) + return -1; + Vec2f n(fun.result); + sv = dynamic_cast<StrokeVertex *>(&(*it)); + Vec2d newPoint(sv->x() + _amount * n.x(), sv->y() + _amount * n.y()); + sv->setPoint(newPoint[0], newPoint[1]); + } + stroke.UpdateLength(); + return 0; } - //!! Bezier curve stroke shader -int BezierCurveShader::shade(Stroke& stroke) const +int BezierCurveShader::shade(Stroke &stroke) const { - if (stroke.strokeVerticesSize() < 4) - return 0; - - // Build the Bezier curve from this set of data points: - vector<Vec2d> data; - StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; - data.push_back(Vec2d(v->x(), v->y())); //first one - StrokeInternal::StrokeVertexIterator previous = v; - ++v; - for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - if (!((fabs(v->x() - (previous)->x()) < M_EPSILON) && ((fabs(v->y() - (previous)->y()) < M_EPSILON)))) - data.push_back(Vec2d(v->x(), v->y())); - previous = v; - } - - // here we build the bezier curve - BezierCurve bcurve(data, _error); - - // bad performances are here !!! // FIXME - vector<Vec2d> CurveVertices; - vector<BezierCurveSegment*>& bsegments = bcurve.segments(); - vector<BezierCurveSegment*>::iterator s = bsegments.begin(), send; - vector<Vec2d>& segmentsVertices = (*s)->vertices(); - vector<Vec2d>::iterator p, pend; - // first point - CurveVertices.push_back(segmentsVertices[0]); - for (send = bsegments.end(); s != send; ++s) { - segmentsVertices = (*s)->vertices(); - p = segmentsVertices.begin(); - ++p; - for (pend = segmentsVertices.end(); p != pend; ++p) { - CurveVertices.push_back((*p)); - } - } - - // Resample the Stroke depending on the number of vertices of the bezier curve: - int originalSize = CurveVertices.size(); + if (stroke.strokeVerticesSize() < 4) + return 0; + + // Build the Bezier curve from this set of data points: + vector<Vec2d> data; + StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend; + data.push_back(Vec2d(v->x(), v->y())); //first one + StrokeInternal::StrokeVertexIterator previous = v; + ++v; + for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + if (!((fabs(v->x() - (previous)->x()) < M_EPSILON) && + ((fabs(v->y() - (previous)->y()) < M_EPSILON)))) + data.push_back(Vec2d(v->x(), v->y())); + previous = v; + } + + // here we build the bezier curve + BezierCurve bcurve(data, _error); + + // bad performances are here !!! // FIXME + vector<Vec2d> CurveVertices; + vector<BezierCurveSegment *> &bsegments = bcurve.segments(); + vector<BezierCurveSegment *>::iterator s = bsegments.begin(), send; + vector<Vec2d> &segmentsVertices = (*s)->vertices(); + vector<Vec2d>::iterator p, pend; + // first point + CurveVertices.push_back(segmentsVertices[0]); + for (send = bsegments.end(); s != send; ++s) { + segmentsVertices = (*s)->vertices(); + p = segmentsVertices.begin(); + ++p; + for (pend = segmentsVertices.end(); p != pend; ++p) { + CurveVertices.push_back((*p)); + } + } + + // Resample the Stroke depending on the number of vertices of the bezier curve: + int originalSize = CurveVertices.size(); #if 0 - float sampling = stroke.ComputeSampling(originalSize); - stroke.Resample(sampling); + float sampling = stroke.ComputeSampling(originalSize); + stroke.Resample(sampling); #endif - stroke.Resample(originalSize); - int newsize = stroke.strokeVerticesSize(); - int nExtraVertex = 0; - if (newsize < originalSize) { - cerr << "Warning: unsufficient resampling" << endl; - } - else { - nExtraVertex = newsize - originalSize; - if (nExtraVertex != 0) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl; - } - } - } - - // assigns the new coordinates: - p = CurveVertices.begin(); - vector<Vec2d>::iterator last = p; - int n; - StrokeInternal::StrokeVertexIterator it, itend; - for (n = 0, it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(), pend = CurveVertices.end(); - (it != itend) && (p != pend); - ++it, ++p, ++n) - { - it->setX(p->x()); - it->setY(p->y()); - last = p; - } - stroke.UpdateLength(); - - // Deal with extra vertices: - if (nExtraVertex == 0) - return 0; - - // nExtraVertex should stay unassigned - vector<StrokeAttribute> attributes; - vector<StrokeVertex*> verticesToRemove; - for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) { - verticesToRemove.push_back(&(*it)); - if (it.isEnd()) { - // XXX Shocking! :P Shouldn't we break in this case??? - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "messed up!" << endl; - } - } - } - for (it = stroke.strokeVerticesBegin(); it != itend; ++it) { - attributes.push_back(it->attribute()); - } - - for (vector<StrokeVertex*>::iterator vr = verticesToRemove.begin(), vrend = verticesToRemove.end(); - vr != vrend; - ++vr) - { - stroke.RemoveVertex(*vr); - } - - vector<StrokeAttribute>::iterator a = attributes.begin(), aend = attributes.end(); - int index = 0; - int index1 = (int)floor((float)originalSize / 2.0); - int index2 = index1 + nExtraVertex; - for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(); - (it != itend) && (a != aend); - ++it) - { - (it)->setAttribute(*a); - if ((index <= index1) || (index > index2)) { - ++a; - } - ++index; - } - return 0; + stroke.Resample(originalSize); + int newsize = stroke.strokeVerticesSize(); + int nExtraVertex = 0; + if (newsize < originalSize) { + cerr << "Warning: unsufficient resampling" << endl; + } + else { + nExtraVertex = newsize - originalSize; + if (nExtraVertex != 0) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl; + } + } + } + + // assigns the new coordinates: + p = CurveVertices.begin(); + vector<Vec2d>::iterator last = p; + int n; + StrokeInternal::StrokeVertexIterator it, itend; + for (n = 0, + it = stroke.strokeVerticesBegin(), + itend = stroke.strokeVerticesEnd(), + pend = CurveVertices.end(); + (it != itend) && (p != pend); + ++it, ++p, ++n) { + it->setX(p->x()); + it->setY(p->y()); + last = p; + } + stroke.UpdateLength(); + + // Deal with extra vertices: + if (nExtraVertex == 0) + return 0; + + // nExtraVertex should stay unassigned + vector<StrokeAttribute> attributes; + vector<StrokeVertex *> verticesToRemove; + for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) { + verticesToRemove.push_back(&(*it)); + if (it.isEnd()) { + // XXX Shocking! :P Shouldn't we break in this case??? + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "messed up!" << endl; + } + } + } + for (it = stroke.strokeVerticesBegin(); it != itend; ++it) { + attributes.push_back(it->attribute()); + } + + for (vector<StrokeVertex *>::iterator vr = verticesToRemove.begin(), + vrend = verticesToRemove.end(); + vr != vrend; + ++vr) { + stroke.RemoveVertex(*vr); + } + + vector<StrokeAttribute>::iterator a = attributes.begin(), aend = attributes.end(); + int index = 0; + int index1 = (int)floor((float)originalSize / 2.0); + int index2 = index1 + nExtraVertex; + for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(); + (it != itend) && (a != aend); + ++it) { + (it)->setAttribute(*a); + if ((index <= index1) || (index > index2)) { + ++a; + } + ++index; + } + return 0; } - -class CurvePiece -{ -public: - StrokeInternal::StrokeVertexIterator _begin; - StrokeInternal::StrokeVertexIterator _last; - Vec2d A; - Vec2d B; - int size; - float _error; - - CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize) - { - _error = 0.0f; - _begin = b; - _last = l; - A = Vec2d((_begin)->x(), (_begin)->y()); - B = Vec2d((_last)->x(), (_last)->y()); - size = iSize; - } - - float error() - { - float maxE = 0.0f; - for (StrokeInternal::StrokeVertexIterator it = _begin; it != _last; ++it) { - Vec2d P(it->x(), it->y()); - float d = GeomUtils::distPointSegment(P, A, B); - if (d > maxE) - maxE = d; - } - _error = maxE; - return maxE; - } - - //! Subdivides the curve into two pieces. - // The first piece is this same object (modified) - // The second piece is returned by the method - CurvePiece *subdivide() - { - StrokeInternal::StrokeVertexIterator it = _begin; - int ns = size - 1; // number of segments (ns > 1) - int ns1 = ns / 2; - int ns2 = ns - ns1; - for (int i = 0; i < ns1; ++it, ++i); - - CurvePiece *second = new CurvePiece(it, _last, ns2 + 1); - size = ns1 + 1; - _last = it; - B = Vec2d((_last)->x(), (_last)->y()); - return second; - } +class CurvePiece { + public: + StrokeInternal::StrokeVertexIterator _begin; + StrokeInternal::StrokeVertexIterator _last; + Vec2d A; + Vec2d B; + int size; + float _error; + + CurvePiece(StrokeInternal::StrokeVertexIterator b, + StrokeInternal::StrokeVertexIterator l, + int iSize) + { + _error = 0.0f; + _begin = b; + _last = l; + A = Vec2d((_begin)->x(), (_begin)->y()); + B = Vec2d((_last)->x(), (_last)->y()); + size = iSize; + } + + float error() + { + float maxE = 0.0f; + for (StrokeInternal::StrokeVertexIterator it = _begin; it != _last; ++it) { + Vec2d P(it->x(), it->y()); + float d = GeomUtils::distPointSegment(P, A, B); + if (d > maxE) + maxE = d; + } + _error = maxE; + return maxE; + } + + //! Subdivides the curve into two pieces. + // The first piece is this same object (modified) + // The second piece is returned by the method + CurvePiece *subdivide() + { + StrokeInternal::StrokeVertexIterator it = _begin; + int ns = size - 1; // number of segments (ns > 1) + int ns1 = ns / 2; + int ns2 = ns - ns1; + for (int i = 0; i < ns1; ++it, ++i) + ; + + CurvePiece *second = new CurvePiece(it, _last, ns2 + 1); + size = ns1 + 1; + _last = it; + B = Vec2d((_last)->x(), (_last)->y()); + return second; + } }; -int PolygonalizationShader::shade(Stroke& stroke) const +int PolygonalizationShader::shade(Stroke &stroke) const { - vector<CurvePiece*> _pieces; - vector<CurvePiece*> _results; - vector<CurvePiece*>::iterator cp, cpend; - - // Compute first approx: - StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd(); - --b; - int size = stroke.strokeVerticesSize(); - - CurvePiece *piece = new CurvePiece(a, b, size); - _pieces.push_back(piece); - - while (!_pieces.empty()) { - piece = _pieces.back(); - _pieces.pop_back(); - if (piece->size > 2 && piece->error() > _error) { - CurvePiece *second = piece->subdivide(); - _pieces.push_back(second); - _pieces.push_back(piece); - } - else { - _results.push_back(piece); - } - } - - // actually modify the geometry for each piece: - for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) { - a = (*cp)->_begin; - b = (*cp)->_last; - Vec2d u = (*cp)->B - (*cp)->A; - Vec2d n(u[1], -u[0]); - n.normalize(); - //Vec2d n(0, 0); - float offset = ((*cp)->_error); - StrokeInternal::StrokeVertexIterator v; - for (v = a; v != b; ++v) { - v->setPoint((*cp)->A.x() + v->u() * u.x() + n.x() * offset, - (*cp)->A.y() + v->u() * u.y() + n.y() * offset); - } + vector<CurvePiece *> _pieces; + vector<CurvePiece *> _results; + vector<CurvePiece *>::iterator cp, cpend; + + // Compute first approx: + StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd(); + --b; + int size = stroke.strokeVerticesSize(); + + CurvePiece *piece = new CurvePiece(a, b, size); + _pieces.push_back(piece); + + while (!_pieces.empty()) { + piece = _pieces.back(); + _pieces.pop_back(); + if (piece->size > 2 && piece->error() > _error) { + CurvePiece *second = piece->subdivide(); + _pieces.push_back(second); + _pieces.push_back(piece); + } + else { + _results.push_back(piece); + } + } + + // actually modify the geometry for each piece: + for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) { + a = (*cp)->_begin; + b = (*cp)->_last; + Vec2d u = (*cp)->B - (*cp)->A; + Vec2d n(u[1], -u[0]); + n.normalize(); + //Vec2d n(0, 0); + float offset = ((*cp)->_error); + StrokeInternal::StrokeVertexIterator v; + for (v = a; v != b; ++v) { + v->setPoint((*cp)->A.x() + v->u() * u.x() + n.x() * offset, + (*cp)->A.y() + v->u() * u.y() + n.y() * offset); + } #if 0 - u.normalize(); - (*a)->setPoint((*a)->x() - u.x() * 10, (*a)->y() - u.y() * 10); + u.normalize(); + (*a)->setPoint((*a)->x() - u.x() * 10, (*a)->y() - u.y() * 10); #endif - } - stroke.UpdateLength(); - - // delete stuff - for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) { - delete (*cp); - } - _results.clear(); - return 0; + } + stroke.UpdateLength(); + + // delete stuff + for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) { + delete (*cp); + } + _results.clear(); + return 0; } -int GuidingLinesShader::shade(Stroke& stroke) const +int GuidingLinesShader::shade(Stroke &stroke) const { - Functions1D::Normal2DF1D norm_fun; - StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd(); - --b; - int size = stroke.strokeVerticesSize(); - CurvePiece piece(a, b, size); - - Vec2d u = piece.B - piece.A; - Vec2f n(u[1], -u[0]); - n.normalize(); - if (norm_fun(stroke) < 0) - return -1; - Vec2f strokeN(norm_fun.result); - if (n * strokeN < 0) { - n[0] = -n[0]; - n[1] = -n[1]; - } - float offset = (piece.error()) / 2.0f * _offset; - StrokeInternal::StrokeVertexIterator v, vend; - for (v = a, vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - v->setPoint(piece.A.x() + v->u() * u.x() + n.x() * offset, - piece.A.y() + v->u() * u.y() + n.y() * offset); - } - stroke.UpdateLength(); - return 0; + Functions1D::Normal2DF1D norm_fun; + StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd(); + --b; + int size = stroke.strokeVerticesSize(); + CurvePiece piece(a, b, size); + + Vec2d u = piece.B - piece.A; + Vec2f n(u[1], -u[0]); + n.normalize(); + if (norm_fun(stroke) < 0) + return -1; + Vec2f strokeN(norm_fun.result); + if (n * strokeN < 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + float offset = (piece.error()) / 2.0f * _offset; + StrokeInternal::StrokeVertexIterator v, vend; + for (v = a, vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + v->setPoint(piece.A.x() + v->u() * u.x() + n.x() * offset, + piece.A.y() + v->u() * u.y() + n.y() * offset); + } + stroke.UpdateLength(); + return 0; } ///////////////////////////////////////// @@ -617,55 +619,54 @@ int GuidingLinesShader::shade(Stroke& stroke) const // ///////////////////////////////////////// - TipRemoverShader::TipRemoverShader(real tipLength) : StrokeShader() { - _tipLength = tipLength; + _tipLength = tipLength; } -int TipRemoverShader::shade(Stroke& stroke) const +int TipRemoverShader::shade(Stroke &stroke) const { - int originalSize = stroke.strokeVerticesSize(); - - if (originalSize < 4) - return 0; - - StrokeInternal::StrokeVertexIterator v, vend; - vector<StrokeVertex*> verticesToRemove; - vector<StrokeAttribute> oldAttributes; - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - if ((v->curvilinearAbscissa() < _tipLength) || (v->strokeLength() - v->curvilinearAbscissa() < _tipLength)) { - verticesToRemove.push_back(&(*v)); - } - oldAttributes.push_back(v->attribute()); - } - - if (originalSize - verticesToRemove.size() < 2) - return 0; - - vector<StrokeVertex*>::iterator sv, svend; - for (sv = verticesToRemove.begin(), svend = verticesToRemove.end(); sv != svend; ++sv) { - stroke.RemoveVertex((*sv)); - } - - // Resample so that our new stroke have the same number of vertices than before - stroke.Resample(originalSize); - - if ((int)stroke.strokeVerticesSize() != originalSize) //soc - cerr << "Warning: resampling problem" << endl; - - // assign old attributes to new stroke vertices: - vector<StrokeAttribute>::iterator a = oldAttributes.begin(), aend = oldAttributes.end(); - for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); - (v != vend) && (a != aend); - ++v, ++a) - { - v->setAttribute(*a); - } - // we're done! - return 0; + int originalSize = stroke.strokeVerticesSize(); + + if (originalSize < 4) + return 0; + + StrokeInternal::StrokeVertexIterator v, vend; + vector<StrokeVertex *> verticesToRemove; + vector<StrokeAttribute> oldAttributes; + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + if ((v->curvilinearAbscissa() < _tipLength) || + (v->strokeLength() - v->curvilinearAbscissa() < _tipLength)) { + verticesToRemove.push_back(&(*v)); + } + oldAttributes.push_back(v->attribute()); + } + + if (originalSize - verticesToRemove.size() < 2) + return 0; + + vector<StrokeVertex *>::iterator sv, svend; + for (sv = verticesToRemove.begin(), svend = verticesToRemove.end(); sv != svend; ++sv) { + stroke.RemoveVertex((*sv)); + } + + // Resample so that our new stroke have the same number of vertices than before + stroke.Resample(originalSize); + + if ((int)stroke.strokeVerticesSize() != originalSize) //soc + cerr << "Warning: resampling problem" << endl; + + // assign old attributes to new stroke vertices: + vector<StrokeAttribute>::iterator a = oldAttributes.begin(), aend = oldAttributes.end(); + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); + (v != vend) && (a != aend); + ++v, ++a) { + v->setAttribute(*a); + } + // we're done! + return 0; } -} // end of namespace StrokeShaders +} // end of namespace StrokeShaders } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h index 55f393c03df..e128817ffa5 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h @@ -51,32 +51,33 @@ namespace StrokeShaders { /*! [ Thickness Shader ]. * Assigns an absolute constant thickness to every vertices of the Stroke. */ -class ConstantThicknessShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param thickness: - * The thickness that must be assigned to the stroke. - */ - ConstantThicknessShader(float thickness) : StrokeShader() - { - _thickness = thickness; - } - - /*! Destructor. */ - virtual ~ConstantThicknessShader() {} - - /*! Returns the string "ConstantThicknessShader".*/ - virtual string getName() const - { - return "ConstantThicknessShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - -private: - float _thickness; +class ConstantThicknessShader : public StrokeShader { + public: + /*! Builds the shader. + * \param thickness: + * The thickness that must be assigned to the stroke. + */ + ConstantThicknessShader(float thickness) : StrokeShader() + { + _thickness = thickness; + } + + /*! Destructor. */ + virtual ~ConstantThicknessShader() + { + } + + /*! Returns the string "ConstantThicknessShader".*/ + virtual string getName() const + { + return "ConstantThicknessShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; + + private: + float _thickness; }; /* [ Thickness Shader ]. @@ -84,25 +85,26 @@ private: * is its thickness from the point to the strip border in the direction pointing outside the object the * Stroke delimitates. */ -class ConstantExternThicknessShader : public StrokeShader -{ -public: - ConstantExternThicknessShader(float thickness) : StrokeShader() - { - _thickness = thickness; - } - - virtual ~ConstantExternThicknessShader() {} - - virtual string getName() const - { - return "ConstantExternThicknessShader"; - } - - virtual int shade(Stroke& stroke) const; - -private: - float _thickness; +class ConstantExternThicknessShader : public StrokeShader { + public: + ConstantExternThicknessShader(float thickness) : StrokeShader() + { + _thickness = thickness; + } + + virtual ~ConstantExternThicknessShader() + { + } + + virtual string getName() const + { + return "ConstantExternThicknessShader"; + } + + virtual int shade(Stroke &stroke) const; + + private: + float _thickness; }; /*! [ Thickness Shader ]. @@ -111,139 +113,140 @@ private: * and the last vertex. * The thickness is linearly interpolated from A to B. */ -class IncreasingThicknessShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param iThicknessMin: - * The first thickness value. - * \param iThicknessMax: - * The second thickness value. - */ - IncreasingThicknessShader(float iThicknessMin, float iThicknessMax) : StrokeShader() - { - _ThicknessMin = iThicknessMin; - _ThicknessMax = iThicknessMax; - } - - /*! Destructor.*/ - virtual ~IncreasingThicknessShader() {} - - virtual string getName() const - { - return "IncreasingThicknessShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - -private: - float _ThicknessMin; - float _ThicknessMax; +class IncreasingThicknessShader : public StrokeShader { + public: + /*! Builds the shader. + * \param iThicknessMin: + * The first thickness value. + * \param iThicknessMax: + * The second thickness value. + */ + IncreasingThicknessShader(float iThicknessMin, float iThicknessMax) : StrokeShader() + { + _ThicknessMin = iThicknessMin; + _ThicknessMax = iThicknessMax; + } + + /*! Destructor.*/ + virtual ~IncreasingThicknessShader() + { + } + + virtual string getName() const + { + return "IncreasingThicknessShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; + + private: + float _ThicknessMin; + float _ThicknessMax; }; /*! [ Thickness shader ]. * Same as previous but here we allow the user to control the ratio thickness/length so that we don't get * fat short lines */ -class ConstrainedIncreasingThicknessShader : public StrokeShader -{ -private: - float _ThicknessMin; - float _ThicknessMax; - float _ratio; - -public: - /*! Builds the shader. - * \param iThicknessMin: - * The first thickness value. - * \param iThicknessMax: - * The second thickness value. - * \param iRatio: - * The ration thickness/length we don't want to exceed. - */ - ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio) : StrokeShader() - { - _ThicknessMin = iThicknessMin; - _ThicknessMax = iThicknessMax; - _ratio = iRatio; - } - - /*! Destructor.*/ - virtual ~ConstrainedIncreasingThicknessShader() {} - - virtual string getName() const - { - return "ConstrainedIncreasingThicknessShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; +class ConstrainedIncreasingThicknessShader : public StrokeShader { + private: + float _ThicknessMin; + float _ThicknessMax; + float _ratio; + + public: + /*! Builds the shader. + * \param iThicknessMin: + * The first thickness value. + * \param iThicknessMax: + * The second thickness value. + * \param iRatio: + * The ration thickness/length we don't want to exceed. + */ + ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio) + : StrokeShader() + { + _ThicknessMin = iThicknessMin; + _ThicknessMax = iThicknessMax; + _ratio = iRatio; + } + + /*! Destructor.*/ + virtual ~ConstrainedIncreasingThicknessShader() + { + } + + virtual string getName() const + { + return "ConstrainedIncreasingThicknessShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; }; /* [ Thickness Shader ]. * Modifys the thickness in a relative way depending on its length. */ -class LengthDependingThicknessShader : public StrokeShader -{ -private: - float _minThickness; - float _maxThickness; - // We divide the strokes in 4 categories: - // l > 300 - // 100 < l < 300 - // 50 < l < 100 - // l < 50 - -public: - LengthDependingThicknessShader(float iMinThickness, float iMaxThickness) : StrokeShader() - { - _minThickness = iMinThickness; - _maxThickness = iMaxThickness; - } - - virtual ~LengthDependingThicknessShader() {} - - virtual string getName() const - { - return "LengthDependingThicknessShader"; - } - - virtual int shade(Stroke& stroke) const; +class LengthDependingThicknessShader : public StrokeShader { + private: + float _minThickness; + float _maxThickness; + // We divide the strokes in 4 categories: + // l > 300 + // 100 < l < 300 + // 50 < l < 100 + // l < 50 + + public: + LengthDependingThicknessShader(float iMinThickness, float iMaxThickness) : StrokeShader() + { + _minThickness = iMinThickness; + _maxThickness = iMaxThickness; + } + + virtual ~LengthDependingThicknessShader() + { + } + + virtual string getName() const + { + return "LengthDependingThicknessShader"; + } + + virtual int shade(Stroke &stroke) const; }; - /*! [ Thickness Shader ]. * Adds some noise to the stroke thickness. * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a>\endhtmlonly */ -class ThicknessNoiseShader : public StrokeShader -{ -private: - float _amplitude; - float _scale; - -public: - ThicknessNoiseShader(); - - /*! Builds a Thickness Noise Shader - * \param iAmplitude: - * The amplitude of the noise signal - * \param iPeriod: - * The period of the noise signal - */ - ThicknessNoiseShader(float iAmplitude, float iPeriod); - - virtual string getName() const - { - return "ThicknessNoiseShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; +class ThicknessNoiseShader : public StrokeShader { + private: + float _amplitude; + float _scale; + + public: + ThicknessNoiseShader(); + + /*! Builds a Thickness Noise Shader + * \param iAmplitude: + * The amplitude of the noise signal + * \param iPeriod: + * The period of the noise signal + */ + ThicknessNoiseShader(float iAmplitude, float iPeriod); + + virtual string getName() const + { + return "ThicknessNoiseShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; }; - // // Color shaders // @@ -251,37 +254,36 @@ public: /*! [ Color Shader ]. * Assigns a constant color to every vertices of the Stroke. */ -class ConstantColorShader : public StrokeShader -{ -public: - /*! Builds the shader from a user-specified color. - * \param iR: - * The red component - * \param iG: - * The green component - * \param iB: - * The blue component - * \param iAlpha: - * The alpha value - */ - ConstantColorShader(float iR, float iG, float iB, float iAlpha = 1.0f) : StrokeShader() - { - _color[0] = iR; - _color[1] = iG; - _color[2] = iB; - _color[3] = iAlpha; - } - - virtual string getName() const - { - return "ConstantColorShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - -private: - float _color[4]; +class ConstantColorShader : public StrokeShader { + public: + /*! Builds the shader from a user-specified color. + * \param iR: + * The red component + * \param iG: + * The green component + * \param iB: + * The blue component + * \param iAlpha: + * The alpha value + */ + ConstantColorShader(float iR, float iG, float iB, float iAlpha = 1.0f) : StrokeShader() + { + _color[0] = iR; + _color[1] = iG; + _color[2] = iB; + _color[3] = iAlpha; + } + + virtual string getName() const + { + return "ConstantColorShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; + + private: + float _color[4]; }; /*! [ Color Shader ]. @@ -289,104 +291,107 @@ private: * The user specifies 2 colors A and B. The stroke color will change linearly from A to B between the * first and the last vertex. */ -class IncreasingColorShader : public StrokeShader -{ -private: - float _colorMin[4]; - float _colorMax[4]; - -public: - /*! Builds the shader from 2 user-specified colors. - * \param iRm: - * The first color red component - * \param iGm: - * The first color green component - * \param iBm: - * The first color blue component - * \param iAlpham: - * The first color alpha value - * \param iRM: - * The second color red component - * \param iGM: - * The second color green component - * \param iBM: - * The second color blue component - * \param iAlphaM: - * The second color alpha value - */ - IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham, - float iRM, float iGM, float iBM, float iAlphaM) - : StrokeShader() - { - _colorMin[0] = iRm; - _colorMin[1] = iGm; - _colorMin[2] = iBm; - _colorMin[3] = iAlpham; - - _colorMax[0] = iRM; - _colorMax[1] = iGM; - _colorMax[2] = iBM; - _colorMax[3] = iAlphaM; - } - - virtual string getName() const - { - return "IncreasingColorShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; +class IncreasingColorShader : public StrokeShader { + private: + float _colorMin[4]; + float _colorMax[4]; + + public: + /*! Builds the shader from 2 user-specified colors. + * \param iRm: + * The first color red component + * \param iGm: + * The first color green component + * \param iBm: + * The first color blue component + * \param iAlpham: + * The first color alpha value + * \param iRM: + * The second color red component + * \param iGM: + * The second color green component + * \param iBM: + * The second color blue component + * \param iAlphaM: + * The second color alpha value + */ + IncreasingColorShader(float iRm, + float iGm, + float iBm, + float iAlpham, + float iRM, + float iGM, + float iBM, + float iAlphaM) + : StrokeShader() + { + _colorMin[0] = iRm; + _colorMin[1] = iGm; + _colorMin[2] = iBm; + _colorMin[3] = iAlpham; + + _colorMax[0] = iRM; + _colorMax[1] = iGM; + _colorMax[2] = iBM; + _colorMax[3] = iAlphaM; + } + + virtual string getName() const + { + return "IncreasingColorShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; }; /* [ Color Shader ]. * Assigns a color to the stroke depending on the material of the shape to which ot belongs to. (Disney shader) */ -class MaterialColorShader : public StrokeShader -{ -private: - float _coefficient; - -public: - MaterialColorShader(float coeff = 1.0f) : StrokeShader() - { - _coefficient = coeff; - } - - virtual string getName() const - { - return "MaterialColorShader"; - } - - virtual int shade(Stroke& stroke) const; +class MaterialColorShader : public StrokeShader { + private: + float _coefficient; + + public: + MaterialColorShader(float coeff = 1.0f) : StrokeShader() + { + _coefficient = coeff; + } + + virtual string getName() const + { + return "MaterialColorShader"; + } + + virtual int shade(Stroke &stroke) const; }; /*! [ Color Shader ]. * Shader to add noise to the stroke colors. */ -class ColorNoiseShader : public StrokeShader -{ -private: - float _amplitude; - float _scale; - -public: - ColorNoiseShader(); - - /*! Builds a Color Noise Shader - * \param iAmplitude: - * The amplitude of the noise signal - * \param iPeriod: - * The period of the noise signal - */ - ColorNoiseShader(float iAmplitude, float iPeriod); - - virtual string getName() const - { - return "ColorNoiseShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; +class ColorNoiseShader : public StrokeShader { + private: + float _amplitude; + float _scale; + + public: + ColorNoiseShader(); + + /*! Builds a Color Noise Shader + * \param iAmplitude: + * The amplitude of the noise signal + * \param iPeriod: + * The period of the noise signal + */ + ColorNoiseShader(float iAmplitude, float iPeriod); + + virtual string getName() const + { + return "ColorNoiseShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke &stroke) const; }; // @@ -396,271 +401,260 @@ public: /*! [ Geometry Shader ]. * Stretches the stroke at its two extremities and following the respective directions: v(1)v(0) and v(n-1)v(n). */ -class BackboneStretcherShader : public StrokeShader -{ -private: - float _amount; - -public: - /*! Builds the shader. - * \param iAmount: - * The stretching amount value. - */ - BackboneStretcherShader(float iAmount = 2.0f) : StrokeShader() - { - _amount = iAmount; - } - - virtual string getName() const - { - return "BackboneStretcherShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class BackboneStretcherShader : public StrokeShader { + private: + float _amount; + + public: + /*! Builds the shader. + * \param iAmount: + * The stretching amount value. + */ + BackboneStretcherShader(float iAmount = 2.0f) : StrokeShader() + { + _amount = iAmount; + } + + virtual string getName() const + { + return "BackboneStretcherShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; /*! [ Geometry Shader. ] * Resamples the stroke. * \see Stroke::Resample(float). */ -class SamplingShader: public StrokeShader -{ -private: - float _sampling; - -public: - /*! Builds the shader. - * \param sampling: - * The sampling to use for the stroke resampling - */ - SamplingShader(float sampling) : StrokeShader() - { - _sampling = sampling; - } - - virtual string getName() const - { - return "SamplingShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class SamplingShader : public StrokeShader { + private: + float _sampling; + + public: + /*! Builds the shader. + * \param sampling: + * The sampling to use for the stroke resampling + */ + SamplingShader(float sampling) : StrokeShader() + { + _sampling = sampling; + } + + virtual string getName() const + { + return "SamplingShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; +class ExternalContourStretcherShader : public StrokeShader { + private: + float _amount; -class ExternalContourStretcherShader : public StrokeShader -{ -private: - float _amount; - -public: - ExternalContourStretcherShader(float iAmount = 2.0f) : StrokeShader() - { - _amount = iAmount; - } + public: + ExternalContourStretcherShader(float iAmount = 2.0f) : StrokeShader() + { + _amount = iAmount; + } - virtual string getName() const - { - return "ExternalContourStretcherShader"; - } + virtual string getName() const + { + return "ExternalContourStretcherShader"; + } - virtual int shade(Stroke& stroke) const; + virtual int shade(Stroke &stroke) const; }; - // Bezier curve stroke shader /*! [ Geometry Shader ]. * Transforms the stroke backbone geometry so that it corresponds to a Bezier Curve approximation of the * original backbone geometry. * \see \htmlonly <a href=bezier/bezier.html>bezier/bezier.html</a> \endhtmlonly */ -class BezierCurveShader : public StrokeShader -{ -private: - float _error; - -public: - /*! Builds the shader. - * \param error: - * The error we're allowing for the approximation. - * This error is the max distance allowed between the new curve and the original geometry. - */ - BezierCurveShader(float error = 4.0) : StrokeShader() - { - _error = error; - } - - virtual string getName() const - { - return "BezierCurveShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class BezierCurveShader : public StrokeShader { + private: + float _error; + + public: + /*! Builds the shader. + * \param error: + * The error we're allowing for the approximation. + * This error is the max distance allowed between the new curve and the original geometry. + */ + BezierCurveShader(float error = 4.0) : StrokeShader() + { + _error = error; + } + + virtual string getName() const + { + return "BezierCurveShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; - /*! [ Geometry Shader ]. * Shader to modify the Stroke geometry so that it looks more "polygonal". * The basic idea is to start from the minimal stroke approximation consisting in a line joining the first vertex * to the last one and to subdivide using the original stroke vertices until a certain error is reached. */ -class PolygonalizationShader : public StrokeShader -{ -private: - float _error; - -public: - /*! Builds the shader. - * \param iError: - * The error we want our polygonal approximation to have with respect to the original geometry. - * The smaller, the closer the new stroke to the orinal one. - * This error corresponds to the maximum distance between the new stroke and the old one. - */ - PolygonalizationShader(float iError) : StrokeShader() - { - _error = iError; - } - - virtual string getName() const - { - return "PolygonalizationShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class PolygonalizationShader : public StrokeShader { + private: + float _error; + + public: + /*! Builds the shader. + * \param iError: + * The error we want our polygonal approximation to have with respect to the original geometry. + * The smaller, the closer the new stroke to the orinal one. + * This error corresponds to the maximum distance between the new stroke and the old one. + */ + PolygonalizationShader(float iError) : StrokeShader() + { + _error = iError; + } + + virtual string getName() const + { + return "PolygonalizationShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; - /*! [ Geometry Shader ]. * Shader to modify the Stroke geometry so that it corresponds to its main direction line. * This shader must be used together with the splitting operator using the curvature criterion. * Indeed, the precision of the approximation will depend on the size of the stroke's pieces. * The bigger the pieces, the rougher the approximation. */ -class GuidingLinesShader : public StrokeShader -{ -private: - float _offset; - -public: - /*! Builds a Guiding Lines shader - * \param iOffset: - * The line that replaces the stroke is initially in the middle of the initial stroke "bbox". - * iOffset is the value of the displacement which is applied to this line along its normal. - */ - GuidingLinesShader(float iOffset) : StrokeShader() - { - _offset = iOffset; - } - - virtual string getName() const - { - return "GuidingLinesShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class GuidingLinesShader : public StrokeShader { + private: + float _offset; + + public: + /*! Builds a Guiding Lines shader + * \param iOffset: + * The line that replaces the stroke is initially in the middle of the initial stroke "bbox". + * iOffset is the value of the displacement which is applied to this line along its normal. + */ + GuidingLinesShader(float iOffset) : StrokeShader() + { + _offset = iOffset; + } + + virtual string getName() const + { + return "GuidingLinesShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; /*! [ Geometry Shader ]. * Removes the stroke's extremities. */ -class TipRemoverShader : public StrokeShader -{ -public: - /*! Builds the shader. - * \param tipLength: - * The length of the piece of stroke we want to remove at each extremity. - */ - TipRemoverShader (real tipLength); - - /*! Destructor. */ - virtual ~TipRemoverShader () {} - - /*! The shading method */ - virtual string getName() const - { - return "TipRemoverShader"; - } - - virtual int shade(Stroke &stroke) const; - -protected: - real _tipLength; +class TipRemoverShader : public StrokeShader { + public: + /*! Builds the shader. + * \param tipLength: + * The length of the piece of stroke we want to remove at each extremity. + */ + TipRemoverShader(real tipLength); + + /*! Destructor. */ + virtual ~TipRemoverShader() + { + } + + /*! The shading method */ + virtual string getName() const + { + return "TipRemoverShader"; + } + + virtual int shade(Stroke &stroke) const; + + protected: + real _tipLength; }; /*! [ Texture Shader ]. * Shader to assign texture to the Stroke material. */ -class BlenderTextureShader : public StrokeShader -{ -private: - MTex *_mtex; - bNodeTree *_nodeTree; - -public: - /*! Builds the shader. - * \param mtex: - * The blender texture to use. - */ - BlenderTextureShader(MTex *mtex) : StrokeShader() - { - _mtex = mtex; - _nodeTree = NULL; - } - - /*! Builds the shader. - * \param nodetree: - * A node tree (of new shading nodes) to define textures. - */ - BlenderTextureShader(bNodeTree *nodetree) : StrokeShader() - { - _nodeTree = nodetree; - _mtex = NULL; - } - - virtual string getName() const - { - return "BlenderTextureShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class BlenderTextureShader : public StrokeShader { + private: + MTex *_mtex; + bNodeTree *_nodeTree; + + public: + /*! Builds the shader. + * \param mtex: + * The blender texture to use. + */ + BlenderTextureShader(MTex *mtex) : StrokeShader() + { + _mtex = mtex; + _nodeTree = NULL; + } + + /*! Builds the shader. + * \param nodetree: + * A node tree (of new shading nodes) to define textures. + */ + BlenderTextureShader(bNodeTree *nodetree) : StrokeShader() + { + _nodeTree = nodetree; + _mtex = NULL; + } + + virtual string getName() const + { + return "BlenderTextureShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; /*! [ Texture Shader ]. * Shader to assign texture to the Stroke material. */ -class StrokeTextureStepShader : public StrokeShader -{ -private: - float _step; - -public: - /*! Builds the shader. - * \param id: - * The number of the preset to use. - */ - StrokeTextureStepShader(float step) : StrokeShader() - { - _step = step; - } - - virtual string getName() const - { - return "StrokeTextureStepShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; +class StrokeTextureStepShader : public StrokeShader { + private: + float _step; + + public: + /*! Builds the shader. + * \param id: + * The number of the preset to use. + */ + StrokeTextureStepShader(float step) : StrokeShader() + { + _step = step; + } + + virtual string getName() const + { + return "StrokeTextureStepShader"; + } + + /*! The shading method */ + virtual int shade(Stroke &stroke) const; }; -} // end of namespace StrokeShaders +} // end of namespace StrokeShaders } /* namespace Freestyle */ -#endif // __FREESTYLE_BASIC_STROKE_SHADERS_H__ +#endif // __FREESTYLE_BASIC_STROKE_SHADERS_H__ diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp index ea5b8334d20..b497b470492 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -42,8 +42,8 @@ //soc #include <QString> extern "C" { -# include "IMB_imbuf.h" -# include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" } using namespace std; @@ -56,409 +56,416 @@ const char *Canvas::_MapsPath = 0; Canvas::Canvas() { - _SelectedFEdge = 0; - _pInstance = this; - PseudoNoise::init(42); - _Renderer = 0; - _current_sm = NULL; - _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP - 1); - _basic = false; + _SelectedFEdge = 0; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = 0; + _current_sm = NULL; + _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP - 1); + _basic = false; } -Canvas::Canvas(const Canvas& iBrother) +Canvas::Canvas(const Canvas &iBrother) { - _SelectedFEdge = iBrother._SelectedFEdge; - _pInstance = this; - PseudoNoise::init(42); - _Renderer = iBrother._Renderer; - _current_sm = iBrother._current_sm; - _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); - _basic = iBrother._basic; + _SelectedFEdge = iBrother._SelectedFEdge; + _pInstance = this; + PseudoNoise::init(42); + _Renderer = iBrother._Renderer; + _current_sm = iBrother._current_sm; + _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); + _basic = iBrother._basic; } Canvas::~Canvas() { - _pInstance = 0; - - Clear(); - if (_Renderer) { - delete _Renderer; - _Renderer = 0; - } - // FIXME: think about an easy control for the maps memory management... - if (!_maps.empty()) { - for (mapsMap::iterator m = _maps.begin(), mend = _maps.end(); m != mend; ++m) { - delete ((*m).second); - } - _maps.clear(); - } - if (_steerableViewMap) - delete _steerableViewMap; + _pInstance = 0; + + Clear(); + if (_Renderer) { + delete _Renderer; + _Renderer = 0; + } + // FIXME: think about an easy control for the maps memory management... + if (!_maps.empty()) { + for (mapsMap::iterator m = _maps.begin(), mend = _maps.end(); m != mend; ++m) { + delete ((*m).second); + } + _maps.clear(); + } + if (_steerableViewMap) + delete _steerableViewMap; } -void Canvas::preDraw() {} +void Canvas::preDraw() +{ +} void Canvas::Draw() { - if (_StyleModules.empty()) - return; - preDraw(); - TimeStamp *timestamp = TimeStamp::instance(); + if (_StyleModules.empty()) + return; + preDraw(); + TimeStamp *timestamp = TimeStamp::instance(); - for (unsigned int i = 0; i < _StyleModules.size(); ++i) { - _current_sm = _StyleModules[i]; + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + _current_sm = _StyleModules[i]; - if (i < _Layers.size() && _Layers[i]) - delete _Layers[i]; + if (i < _Layers.size() && _Layers[i]) + delete _Layers[i]; - _Layers[i] = _StyleModules[i]->execute(); - if (!_Layers[i]) - continue; + _Layers[i] = _StyleModules[i]->execute(); + if (!_Layers[i]) + continue; - stroke_count += _Layers[i]->strokes_size(); + stroke_count += _Layers[i]->strokes_size(); - timestamp->increment(); - } - postDraw(); + timestamp->increment(); + } + postDraw(); } void Canvas::postDraw() { - update(); + update(); } void Canvas::Clear() { - if (!_Layers.empty()) { - for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) { - if (*sl) - delete (*sl); - } - _Layers.clear(); - } - - if (!_StyleModules.empty()) { - for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s) { - if (*s) - delete (*s); - } - _StyleModules.clear(); - } - if (_steerableViewMap) - _steerableViewMap->Reset(); - - stroke_count = 0; + if (!_Layers.empty()) { + for (deque<StrokeLayer *>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; + ++sl) { + if (*sl) + delete (*sl); + } + _Layers.clear(); + } + + if (!_StyleModules.empty()) { + for (deque<StyleModule *>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); + s != send; + ++s) { + if (*s) + delete (*s); + } + _StyleModules.clear(); + } + if (_steerableViewMap) + _steerableViewMap->Reset(); + + stroke_count = 0; } void Canvas::Erase() { - if (!_Layers.empty()) { - for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) { - if (*sl) - (*sl)->clear(); - } - } - if (_steerableViewMap) - _steerableViewMap->Reset(); - update(); - - stroke_count = 0; + if (!_Layers.empty()) { + for (deque<StrokeLayer *>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; + ++sl) { + if (*sl) + (*sl)->clear(); + } + } + if (_steerableViewMap) + _steerableViewMap->Reset(); + update(); + + stroke_count = 0; } void Canvas::PushBackStyleModule(StyleModule *iStyleModule) { - StrokeLayer *layer = new StrokeLayer(); - _StyleModules.push_back(iStyleModule); - _Layers.push_back(layer); + StrokeLayer *layer = new StrokeLayer(); + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); } void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) { - unsigned size = _StyleModules.size(); - StrokeLayer *layer = new StrokeLayer(); - if ((_StyleModules.empty()) || (index == size)) { - _StyleModules.push_back(iStyleModule); - _Layers.push_back(layer); - return; - } - _StyleModules.insert(_StyleModules.begin() + index, iStyleModule); - _Layers.insert(_Layers.begin() + index, layer); + unsigned size = _StyleModules.size(); + StrokeLayer *layer = new StrokeLayer(); + if ((_StyleModules.empty()) || (index == size)) { + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); + return; + } + _StyleModules.insert(_StyleModules.begin() + index, iStyleModule); + _Layers.insert(_Layers.begin() + index, layer); } void Canvas::RemoveStyleModule(unsigned index) { - unsigned int i = 0; - if (!_StyleModules.empty()) { - for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); - s != send; - ++s, ++i) - { - if (i == index) { - // remove shader - if (*s) - delete *s; - _StyleModules.erase(s); - break; - } - } - } - - if (!_Layers.empty()) { - i = 0; - for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); - sl != slend; - ++sl, ++i) - { - if (i == index) { - // remove layer - if (*sl) - delete *sl; - _Layers.erase(sl); - break; - } - } - } + unsigned int i = 0; + if (!_StyleModules.empty()) { + for (deque<StyleModule *>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); + s != send; + ++s, ++i) { + if (i == index) { + // remove shader + if (*s) + delete *s; + _StyleModules.erase(s); + break; + } + } + } + + if (!_Layers.empty()) { + i = 0; + for (deque<StrokeLayer *>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; + ++sl, ++i) { + if (i == index) { + // remove layer + if (*sl) + delete *sl; + _Layers.erase(sl); + break; + } + } + } } void Canvas::SwapStyleModules(unsigned i1, unsigned i2) { - StyleModule *tmp; - tmp = _StyleModules[i1]; - _StyleModules[i1] = _StyleModules[i2]; - _StyleModules[i2] = tmp; - - StrokeLayer *tmp2; - tmp2 = _Layers[i1]; - _Layers[i1] = _Layers[i2]; - _Layers[i2] = tmp2; + StyleModule *tmp; + tmp = _StyleModules[i1]; + _StyleModules[i1] = _StyleModules[i2]; + _StyleModules[i2] = tmp; + + StrokeLayer *tmp2; + tmp2 = _Layers[i1]; + _Layers[i1] = _Layers[i2]; + _Layers[i2] = tmp2; } void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule) { - unsigned i = 0; - for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s, ++i) { - if (i == index) { - if (*s) - delete *s; - *s = iStyleModule; - break; - } - } + unsigned i = 0; + for (deque<StyleModule *>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); + s != send; + ++s, ++i) { + if (i == index) { + if (*s) + delete *s; + *s = iStyleModule; + break; + } + } } void Canvas::setVisible(unsigned index, bool iVisible) { - _StyleModules[index]->setDisplayed(iVisible); + _StyleModules[index]->setDisplayed(iVisible); } void Canvas::setModified(unsigned index, bool iMod) { - _StyleModules[index]->setModified(iMod); + _StyleModules[index]->setModified(iMod); } -void Canvas::resetModified(bool iMod/* = false */) +void Canvas::resetModified(bool iMod /* = false */) { - unsigned int size = _StyleModules.size(); - for (unsigned int i = 0; i < size; ++i) - setModified(i, iMod); + unsigned int size = _StyleModules.size(); + for (unsigned int i = 0; i < size; ++i) + setModified(i, iMod); } -void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) +void Canvas::causalStyleModules(vector<unsigned> &vec, unsigned index) { - unsigned int size = _StyleModules.size(); + unsigned int size = _StyleModules.size(); - for (unsigned int i = index; i < size; ++i) { - if (_StyleModules[i]->getCausal()) - vec.push_back(i); - } + for (unsigned int i = index; i < size; ++i) { + if (_StyleModules[i]->getCausal()) + vec.push_back(i); + } } void Canvas::Render(const StrokeRenderer *iRenderer) { - for (unsigned int i = 0; i < _StyleModules.size(); ++i) { - if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) - continue; - _Layers[i]->Render(iRenderer); - } + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->Render(iRenderer); + } } void Canvas::RenderBasic(const StrokeRenderer *iRenderer) { - for (unsigned int i = 0; i < _StyleModules.size(); ++i) { - if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) - continue; - _Layers[i]->RenderBasic(iRenderer); - } + for (unsigned int i = 0; i < _StyleModules.size(); ++i) { + if (!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->RenderBasic(iRenderer); + } } -void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma) +void Canvas::loadMap(const char *iFileName, + const char *iMapName, + unsigned int iNbLevels, + float iSigma) { - // check whether this map was already loaded: - if (!_maps.empty()) { - mapsMap::iterator m = _maps.find(iMapName); - if (m != _maps.end()) { - // lazy check for size changes - ImagePyramid *pyramid = (*m).second; - if ((pyramid->width() != width()) || (pyramid->height() != height())) { - delete pyramid; - } - else { - return; - } - } - } - - string filePath; - if (_MapsPath) { - filePath = _MapsPath; - filePath += iFileName; - } - else { - filePath = iFileName; - } - -#if 0 //soc - QImage *qimg; - QImage newMap(filePath.c_str()); - if (newMap.isNull()) { - cerr << "Could not load image file " << filePath << endl; - return; - } - qimg = &newMap; + // check whether this map was already loaded: + if (!_maps.empty()) { + mapsMap::iterator m = _maps.find(iMapName); + if (m != _maps.end()) { + // lazy check for size changes + ImagePyramid *pyramid = (*m).second; + if ((pyramid->width() != width()) || (pyramid->height() != height())) { + delete pyramid; + } + else { + return; + } + } + } + + string filePath; + if (_MapsPath) { + filePath = _MapsPath; + filePath += iFileName; + } + else { + filePath = iFileName; + } + +#if 0 //soc + QImage *qimg; + QImage newMap(filePath.c_str()); + if (newMap.isNull()) { + cerr << "Could not load image file " << filePath << endl; + return; + } + qimg = &newMap; #endif - /* OCIO_TODO: support different input color space */ - ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); - if (qimg == 0) { - cerr << "Could not load image file " << filePath << endl; - return; - } - -#if 0 // soc - // resize - QImage scaledImg; - if ((newMap.width() != width()) || (newMap.height() != height())) { - scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - qimg = &scaledImg; - } + /* OCIO_TODO: support different input color space */ + ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); + if (qimg == 0) { + cerr << "Could not load image file " << filePath << endl; + return; + } + +#if 0 // soc + // resize + QImage scaledImg; + if ((newMap.width() != width()) || (newMap.height() != height())) { + scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + qimg = &scaledImg; + } #endif - ImBuf *scaledImg; - if ((qimg->x != width()) || (qimg->y != height())) { - scaledImg = IMB_dupImBuf(qimg); - IMB_scaleImBuf(scaledImg, width(), height()); - } - + ImBuf *scaledImg; + if ((qimg->x != width()) || (qimg->y != height())) { + scaledImg = IMB_dupImBuf(qimg); + IMB_scaleImBuf(scaledImg, width(), height()); + } - // deal with color image + // deal with color image #if 0 - if (newMap->depth() != 8) { - int w = newMap->width(); - int h = newMap->height(); - QImage *tmp = new QImage(w, h, 8); - for (unsigned int y = 0; y < h; ++y) { - for (unsigned int x = 0; x < w; ++x) { - int c = qGray(newMap->pixel(x, y)); - tmp->setPixel(x, y, c); - } - } - delete newMap; - newMap = tmp; - } + if (newMap->depth() != 8) { + int w = newMap->width(); + int h = newMap->height(); + QImage *tmp = new QImage(w, h, 8); + for (unsigned int y = 0; y < h; ++y) { + for (unsigned int x = 0; x < w; ++x) { + int c = qGray(newMap->pixel(x, y)); + tmp->setPixel(x, y, c); + } + } + delete newMap; + newMap = tmp; + } #endif - int x, y; - int w = qimg->x; - int h = qimg->y; - int rowbytes = w * 4; - GrayImage tmp(w, h); - char *pix; - - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - pix = (char *)qimg->rect + y * rowbytes + x * 4; - float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32; - tmp.setPixel(x, y, c); - } - } + int x, y; + int w = qimg->x; + int h = qimg->y; + int rowbytes = w * 4; + GrayImage tmp(w, h); + char *pix; + + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + pix = (char *)qimg->rect + y * rowbytes + x * 4; + float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32; + tmp.setPixel(x, y, c); + } + } #if 0 - GrayImage blur(w, h); - GaussianFilter gf(4.0f); - //int bound = gf.getBound(); - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y); - blur.setPixel(x, y, c); - } - } + GrayImage blur(w, h); + GaussianFilter gf(4.0f); + //int bound = gf.getBound(); + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y); + blur.setPixel(x, y, c); + } + } #endif - GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); - int ow = pyramid->width(0); - int oh = pyramid->height(0); - string base(iMapName); //soc - for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) { - // save each image: + GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); + int ow = pyramid->width(0); + int oh = pyramid->height(0); + string base(iMapName); //soc + for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) { + // save each image: #if 0 - w = pyramid.width(i); - h = pyramid.height(i); + w = pyramid.width(i); + h = pyramid.height(i); #endif - //soc QImage qtmp(ow, oh, QImage::Format_RGB32); - ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); - - //int k = (1 << i); - for (y = 0; y < oh; ++y) { - for (x = 0; x < ow; ++x) { - int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i); - //soc qtmp.setPixel(x, y, qRgb(c, c, c)); - pix = (char *)qtmp->rect + y * rowbytes + x * 4; - pix[0] = pix[1] = pix[2] = c; - } - } - //soc qtmp.save(base + QString::number(i) + ".bmp", "BMP"); - stringstream filename; - filename << base; - filename << i << ".bmp"; - qtmp->ftype = IMB_FTYPE_BMP; - IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); - } + //soc QImage qtmp(ow, oh, QImage::Format_RGB32); + ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); + + //int k = (1 << i); + for (y = 0; y < oh; ++y) { + for (x = 0; x < ow; ++x) { + int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i); + //soc qtmp.setPixel(x, y, qRgb(c, c, c)); + pix = (char *)qtmp->rect + y * rowbytes + x * 4; + pix[0] = pix[1] = pix[2] = c; + } + } + //soc qtmp.save(base + QString::number(i) + ".bmp", "BMP"); + stringstream filename; + filename << base; + filename << i << ".bmp"; + qtmp->ftype = IMB_FTYPE_BMP; + IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0); + } #if 0 - QImage *qtmp = new QImage(w, h, 32); - for (y = 0; y < h; ++y) { - for (x = 0; x < w; ++x) { - int c = (int)blur.pixel(x, y); - qtmp->setPixel(x, y, qRgb(c, c, c)); - } - } - delete newMap; - newMap = qtmp; + QImage *qtmp = new QImage(w, h, 32); + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + int c = (int)blur.pixel(x, y); + qtmp->setPixel(x, y, qRgb(c, c, c)); + } + } + delete newMap; + newMap = qtmp; #endif - _maps[iMapName] = pyramid; - //newMap->save("toto.bmp", "BMP"); + _maps[iMapName] = pyramid; + //newMap->save("toto.bmp", "BMP"); } float Canvas::readMapPixel(const char *iMapName, int level, int x, int y) { - if (_maps.empty()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "readMapPixel warning: no map was loaded "<< endl; - } - return -1; - } - mapsMap::iterator m = _maps.find(iMapName); - if (m == _maps.end()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; - } - return -1; - } - ImagePyramid *pyramid = (*m).second; - if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height())) - return 0; - - return pyramid->pixel(x, height() - 1 - y, level); + if (_maps.empty()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "readMapPixel warning: no map was loaded " << endl; + } + return -1; + } + mapsMap::iterator m = _maps.find(iMapName); + if (m == _maps.end()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; + } + return -1; + } + ImagePyramid *pyramid = (*m).second; + if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height())) + return 0; + + return pyramid->pixel(x, height() - 1 - y, level); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h index 9431b37395c..e059bb07eda 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.h +++ b/source/blender/freestyle/intern/stroke/Canvas.h @@ -35,19 +35,18 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { using namespace Geometry; -struct ltstr -{ - bool operator()(const char *s1, const char *s2) const - { - return strcmp(s1, s2) < 0; - } +struct ltstr { + bool operator()(const char *s1, const char *s2) const + { + return strcmp(s1, s2) < 0; + } }; class InformationMap; @@ -65,189 +64,191 @@ class StyleModule; /*! Class to define the canvas on which strokes are drawn. * It's used to store state information about the drawing. */ -class Canvas -{ -public: - /*! Returns a pointer on the Canvas instance */ - static Canvas *getInstance() - { - return _pInstance; - } - - typedef std::map<const char *, ImagePyramid *, ltstr> mapsMap; - static const int NB_STEERABLE_VIEWMAP = 5; - -protected: - static Canvas *_pInstance; - std::deque<StrokeLayer*> _Layers; - std::deque<StyleModule*> _StyleModules; - FEdge *_SelectedFEdge; - - StrokeRenderer *_Renderer; - StyleModule *_current_sm; - mapsMap _maps; - static const char *_MapsPath; - SteerableViewMap *_steerableViewMap; - bool _basic; - int stroke_count; - -public: - /* Builds the Canvas */ - Canvas(); - /* Copy constructor */ - Canvas(const Canvas& iBrother); - /* Destructor */ - virtual ~Canvas(); - - /* operations that need to be done before a draw */ - virtual void preDraw(); - - /* Draw the canvas using the current shader */ - virtual void Draw(); - - /* operations that need to be done after a draw */ - virtual void postDraw(); - - /* Renders the created strokes */ - virtual void Render(const StrokeRenderer *iRenderer); - /* Basic Renders the created strokes */ - virtual void RenderBasic(const StrokeRenderer *iRenderer); - /* Renders a stroke */ - virtual void RenderStroke(Stroke *iStroke) = 0; - - /* init the canvas */ - virtual void init() = 0; - - /* Clears the Canvas (shaders stack, layers stack...) */ - void Clear(); - - /* Erases the layers */ - virtual void Erase(); - - /* Reads a pixel area from the canvas */ - virtual void readColorPixels(int x, int y, int w, int h, RGBImage& oImage) const = 0; - /* Reads a depth pixel area from the canvas */ - virtual void readDepthPixels(int x, int y, int w, int h, GrayImage& oImage) const = 0; - - /* update the canvas (display) */ - virtual void update() = 0; - - /* checks whether the canvas is empty or not */ - bool isEmpty() const - { - return (_Layers.empty()); - } - - /* Maps management */ - /*! Loads an image map. The map will be scaled (without preserving the ratio in order to fit the actual - * canvas size.). - * The image must be a gray values image... - * \param iFileName: - * The name of the image file - * \param iMapName: - * The name that will be used to access this image - * \param iNbLevels: - * The number of levels in the map pyramid. (default = 4). - * If iNbLevels == 0, the complete pyramid is built. - */ - void loadMap(const char *iFileName, const char *iMapName, unsigned iNbLevels = 4, float iSigma = 1.0f); - - /*! Reads a pixel value in a map. - * Returns a value between 0 and 1. - * \param iMapName: - * The name of the map - * \param level: - * The level of the pyramid from which the pixel must be read. - * \param x: - * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. - * \param y: - * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. - */ - float readMapPixel(const char *iMapName, int level, int x, int y); - - /*! Sets the steerable viewmap */ - void loadSteerableViewMap(SteerableViewMap *iSVM) - { - _steerableViewMap = iSVM; - } - - /*! Returns the steerable VM */ - SteerableViewMap *getSteerableViewMap() - { - return _steerableViewMap; - } - - /*! accessors */ - inline const FEdge *selectedFEdge() const - { - return _SelectedFEdge; - } - - inline FEdge *selectedFEdge() - { - return _SelectedFEdge; - } - - virtual int width() const = 0; - virtual int height() const = 0; - virtual BBox<Vec2i> border() const = 0; - virtual BBox<Vec3r> scene3DBBox() const = 0; - - inline const StrokeRenderer *renderer() const - { - return _Renderer; - } - - inline StyleModule *getCurrentStyleModule() - { - return _current_sm; - } - - virtual bool getRecordFlag() const - { - return false; - } - - inline int getStrokeCount() const - { - return stroke_count; - } - - /*! modifiers */ - inline void setSelectedFEdge(FEdge *iFEdge) - { - _SelectedFEdge = iFEdge; - } - - /*! inserts a shader at pos index+1 */ - void PushBackStyleModule(StyleModule *iStyleModule); - void InsertStyleModule(unsigned index, StyleModule *iStyleModule); - void RemoveStyleModule(unsigned index); - void SwapStyleModules(unsigned i1, unsigned i2); - void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule); - void setVisible(unsigned index, bool iVisible) ; +class Canvas { + public: + /*! Returns a pointer on the Canvas instance */ + static Canvas *getInstance() + { + return _pInstance; + } + + typedef std::map<const char *, ImagePyramid *, ltstr> mapsMap; + static const int NB_STEERABLE_VIEWMAP = 5; + + protected: + static Canvas *_pInstance; + std::deque<StrokeLayer *> _Layers; + std::deque<StyleModule *> _StyleModules; + FEdge *_SelectedFEdge; + + StrokeRenderer *_Renderer; + StyleModule *_current_sm; + mapsMap _maps; + static const char *_MapsPath; + SteerableViewMap *_steerableViewMap; + bool _basic; + int stroke_count; + + public: + /* Builds the Canvas */ + Canvas(); + /* Copy constructor */ + Canvas(const Canvas &iBrother); + /* Destructor */ + virtual ~Canvas(); + + /* operations that need to be done before a draw */ + virtual void preDraw(); + + /* Draw the canvas using the current shader */ + virtual void Draw(); + + /* operations that need to be done after a draw */ + virtual void postDraw(); + + /* Renders the created strokes */ + virtual void Render(const StrokeRenderer *iRenderer); + /* Basic Renders the created strokes */ + virtual void RenderBasic(const StrokeRenderer *iRenderer); + /* Renders a stroke */ + virtual void RenderStroke(Stroke *iStroke) = 0; + + /* init the canvas */ + virtual void init() = 0; + + /* Clears the Canvas (shaders stack, layers stack...) */ + void Clear(); + + /* Erases the layers */ + virtual void Erase(); + + /* Reads a pixel area from the canvas */ + virtual void readColorPixels(int x, int y, int w, int h, RGBImage &oImage) const = 0; + /* Reads a depth pixel area from the canvas */ + virtual void readDepthPixels(int x, int y, int w, int h, GrayImage &oImage) const = 0; + + /* update the canvas (display) */ + virtual void update() = 0; + + /* checks whether the canvas is empty or not */ + bool isEmpty() const + { + return (_Layers.empty()); + } + + /* Maps management */ + /*! Loads an image map. The map will be scaled (without preserving the ratio in order to fit the actual + * canvas size.). + * The image must be a gray values image... + * \param iFileName: + * The name of the image file + * \param iMapName: + * The name that will be used to access this image + * \param iNbLevels: + * The number of levels in the map pyramid. (default = 4). + * If iNbLevels == 0, the complete pyramid is built. + */ + void loadMap(const char *iFileName, + const char *iMapName, + unsigned iNbLevels = 4, + float iSigma = 1.0f); + + /*! Reads a pixel value in a map. + * Returns a value between 0 and 1. + * \param iMapName: + * The name of the map + * \param level: + * The level of the pyramid from which the pixel must be read. + * \param x: + * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. + * \param y: + * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. + */ + float readMapPixel(const char *iMapName, int level, int x, int y); + + /*! Sets the steerable viewmap */ + void loadSteerableViewMap(SteerableViewMap *iSVM) + { + _steerableViewMap = iSVM; + } + + /*! Returns the steerable VM */ + SteerableViewMap *getSteerableViewMap() + { + return _steerableViewMap; + } + + /*! accessors */ + inline const FEdge *selectedFEdge() const + { + return _SelectedFEdge; + } + + inline FEdge *selectedFEdge() + { + return _SelectedFEdge; + } + + virtual int width() const = 0; + virtual int height() const = 0; + virtual BBox<Vec2i> border() const = 0; + virtual BBox<Vec3r> scene3DBBox() const = 0; + + inline const StrokeRenderer *renderer() const + { + return _Renderer; + } + + inline StyleModule *getCurrentStyleModule() + { + return _current_sm; + } + + virtual bool getRecordFlag() const + { + return false; + } + + inline int getStrokeCount() const + { + return stroke_count; + } + + /*! modifiers */ + inline void setSelectedFEdge(FEdge *iFEdge) + { + _SelectedFEdge = iFEdge; + } + + /*! inserts a shader at pos index+1 */ + void PushBackStyleModule(StyleModule *iStyleModule); + void InsertStyleModule(unsigned index, StyleModule *iStyleModule); + void RemoveStyleModule(unsigned index); + void SwapStyleModules(unsigned i1, unsigned i2); + void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule); + void setVisible(unsigned index, bool iVisible); #if 0 - inline void setDensityMap(InformationMap<RGBImage> *iMap) - { - _DensityMap = iMap; - } + inline void setDensityMap(InformationMap<RGBImage> *iMap) + { + _DensityMap = iMap; + } #endif - inline void AddLayer(StrokeLayer *iLayer) - { - _Layers.push_back(iLayer); - } + inline void AddLayer(StrokeLayer *iLayer) + { + _Layers.push_back(iLayer); + } - void resetModified(bool iMod = false); - void causalStyleModules(std::vector<unsigned>& vec, unsigned index = 0); - void setModified(unsigned index, bool b); + void resetModified(bool iMod = false); + void causalStyleModules(std::vector<unsigned> &vec, unsigned index = 0); + void setModified(unsigned index, bool b); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Canvas") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Canvas") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_CANVAS_H__ +#endif // __FREESTYLE_CANVAS_H__ diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp index 53e5c24352c..32b3ec2de31 100644 --- a/source/blender/freestyle/intern/stroke/Chain.cpp +++ b/source/blender/freestyle/intern/stroke/Chain.cpp @@ -28,122 +28,124 @@ namespace Freestyle { void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation) { - ViewEdge::vertex_iterator v; - ViewEdge::vertex_iterator vend; - ViewEdge::vertex_iterator vfirst; - Vec3r previous, current; - if (true == orientation) { - v = iViewEdge->vertices_begin(); - vfirst = v; - vend = iViewEdge->vertices_end(); - } - else { - v = iViewEdge->vertices_last(); - vfirst = v; - vend = iViewEdge->vertices_end(); - } + ViewEdge::vertex_iterator v; + ViewEdge::vertex_iterator vend; + ViewEdge::vertex_iterator vfirst; + Vec3r previous, current; + if (true == orientation) { + v = iViewEdge->vertices_begin(); + vfirst = v; + vend = iViewEdge->vertices_end(); + } + else { + v = iViewEdge->vertices_last(); + vfirst = v; + vend = iViewEdge->vertices_end(); + } - if (!_Vertices.empty()) { - previous = _Vertices.back()->point2d(); - if (orientation) - ++v; - else - --v; - // Ensure the continuity of underlying FEdges - CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); - SVertex *sv_first = (*vfirst); - FEdge *fe = _fedgeB->duplicate(); - fe->setTemporary(true); - fe->setVertexB(sv_first); - fe->vertexA()->shape()->AddEdge(fe); - fe->vertexA()->AddFEdge(fe); - fe->vertexB()->AddFEdge(fe); - cp->setA(sv_first); - } - else { - previous = (*v)->point2d(); - } - do { - current = (*v)->point2d(); - Curve::push_vertex_back(*v); - //_Length += (current - previous).norm(); - previous = current; - if (orientation) - ++v; - else - --v; - } while ((v != vend) && (v != vfirst)); + if (!_Vertices.empty()) { + previous = _Vertices.back()->point2d(); + if (orientation) + ++v; + else + --v; + // Ensure the continuity of underlying FEdges + CurvePoint *cp = + _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); + SVertex *sv_first = (*vfirst); + FEdge *fe = _fedgeB->duplicate(); + fe->setTemporary(true); + fe->setVertexB(sv_first); + fe->vertexA()->shape()->AddEdge(fe); + fe->vertexA()->AddFEdge(fe); + fe->vertexB()->AddFEdge(fe); + cp->setA(sv_first); + } + else { + previous = (*v)->point2d(); + } + do { + current = (*v)->point2d(); + Curve::push_vertex_back(*v); + //_Length += (current - previous).norm(); + previous = current; + if (orientation) + ++v; + else + --v; + } while ((v != vend) && (v != vfirst)); - if (v == vfirst) { - //Add last one: - current = (*v)->point2d(); - Curve::push_vertex_back(*v); - //_Length += (current - previous).norm(); - } + if (v == vfirst) { + //Add last one: + current = (*v)->point2d(); + Curve::push_vertex_back(*v); + //_Length += (current - previous).norm(); + } - _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); + _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); } void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation) { - orientation = !orientation; - ViewEdge::vertex_iterator v; - ViewEdge::vertex_iterator vend; - ViewEdge::vertex_iterator vfirst; - Vec3r previous, current; - if (true == orientation) { - v = iViewEdge->vertices_begin(); - vfirst = v; - vend = iViewEdge->vertices_end(); - } - else { - v = iViewEdge->vertices_last(); - vfirst = v; - vend = iViewEdge->vertices_end(); - } + orientation = !orientation; + ViewEdge::vertex_iterator v; + ViewEdge::vertex_iterator vend; + ViewEdge::vertex_iterator vfirst; + Vec3r previous, current; + if (true == orientation) { + v = iViewEdge->vertices_begin(); + vfirst = v; + vend = iViewEdge->vertices_end(); + } + else { + v = iViewEdge->vertices_last(); + vfirst = v; + vend = iViewEdge->vertices_end(); + } - if (!_Vertices.empty()) { - previous = _Vertices.front()->point2d(); - if (orientation) - ++v; - else - --v; - // Ensure the continuity of underlying FEdges - CurvePoint *cp = _Vertices.front(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); - SVertex *sv_last = cp->A(); - SVertex *sv_curr = (*v); - FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB(); - FEdge *fe2 = fe->duplicate(); - fe2->setTemporary(true); - fe2->setVertexA(sv_curr); - fe2->setVertexB(sv_last); - sv_last->AddFEdge(fe2); - sv_curr->AddFEdge(fe2); - sv_curr->shape()->AddEdge(fe2); - } - else { - previous = (*v)->point2d(); - } - do { - current = (*v)->point2d(); - Curve::push_vertex_front((*v)); - //_Length += (current - previous).norm(); - previous = current; - if (orientation) - ++v; - else - --v; - } while ((v != vend) && (v != vfirst)); + if (!_Vertices.empty()) { + previous = _Vertices.front()->point2d(); + if (orientation) + ++v; + else + --v; + // Ensure the continuity of underlying FEdges + CurvePoint *cp = + _Vertices.front(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); + SVertex *sv_last = cp->A(); + SVertex *sv_curr = (*v); + FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB(); + FEdge *fe2 = fe->duplicate(); + fe2->setTemporary(true); + fe2->setVertexA(sv_curr); + fe2->setVertexB(sv_last); + sv_last->AddFEdge(fe2); + sv_curr->AddFEdge(fe2); + sv_curr->shape()->AddEdge(fe2); + } + else { + previous = (*v)->point2d(); + } + do { + current = (*v)->point2d(); + Curve::push_vertex_front((*v)); + //_Length += (current - previous).norm(); + previous = current; + if (orientation) + ++v; + else + --v; + } while ((v != vend) && (v != vfirst)); - if (v == vfirst) { - //Add last one: - current = (*v)->point2d(); - Curve::push_vertex_front(*v); - //_Length += (current - previous).norm(); - } + if (v == vfirst) { + //Add last one: + current = (*v)->point2d(); + Curve::push_vertex_front(*v); + //_Length += (current - previous).norm(); + } - if (!_fedgeB) - _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); + if (!_fedgeB) + _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h index 21421c7298f..547fed70953 100644 --- a/source/blender/freestyle/intern/stroke/Chain.h +++ b/source/blender/freestyle/intern/stroke/Chain.h @@ -31,81 +31,82 @@ namespace Freestyle { /*! Class to represent a 1D elements issued from the chaining process. * A Chain is the last step before the Stroke and is used in the Splitting and Creation processes. */ -class Chain : public Curve -{ -protected: - // tmp - Id *_splittingId; - FEdge *_fedgeB; // the last FEdge of the ViewEdge passed to the last call for push_viewedge_back(). - -public: - /*! Defult constructor. */ - Chain() : Curve() - { - _splittingId = 0; - _fedgeB = 0; - } - - /*! Builds a chain from its Id. */ - Chain(const Id& id) : Curve(id) - { - _splittingId = 0; - _fedgeB = 0; - } - - /*! Copy Constructor */ - Chain(const Chain& iBrother) : Curve(iBrother) - { - _splittingId = iBrother._splittingId; - _fedgeB = iBrother._fedgeB; - } - - /*! Destructor. */ - virtual ~Chain() { - // only the last splitted deletes this id - if (_splittingId) { - if (*_splittingId == _Id) - delete _splittingId; - } - } - - /*! Returns the string "Chain" */ - virtual string getExactTypeName() const - { - return "Chain"; - } - - /*! Adds a ViewEdge at the end of the chain - * \param iViewEdge: - * The ViewEdge that must be added. - * \param orientation: - * The orientation with which this ViewEdge must be processed. - */ - void push_viewedge_back(ViewEdge *iViewEdge, bool orientation); - - /*! Adds a ViewEdge at the beginning of the chain - * \param iViewEdge: - * The ViewEdge that must be added. - * \param orientation: - * The orientation with which this ViewEdge must be processed. - */ - void push_viewedge_front(ViewEdge *iViewEdge, bool orientation); - - inline void setSplittingId(Id *sid) - { - _splittingId = sid; - } - - inline Id *getSplittingId() - { - return _splittingId; - } +class Chain : public Curve { + protected: + // tmp + Id *_splittingId; + FEdge * + _fedgeB; // the last FEdge of the ViewEdge passed to the last call for push_viewedge_back(). + + public: + /*! Defult constructor. */ + Chain() : Curve() + { + _splittingId = 0; + _fedgeB = 0; + } + + /*! Builds a chain from its Id. */ + Chain(const Id &id) : Curve(id) + { + _splittingId = 0; + _fedgeB = 0; + } + + /*! Copy Constructor */ + Chain(const Chain &iBrother) : Curve(iBrother) + { + _splittingId = iBrother._splittingId; + _fedgeB = iBrother._fedgeB; + } + + /*! Destructor. */ + virtual ~Chain() + { + // only the last splitted deletes this id + if (_splittingId) { + if (*_splittingId == _Id) + delete _splittingId; + } + } + + /*! Returns the string "Chain" */ + virtual string getExactTypeName() const + { + return "Chain"; + } + + /*! Adds a ViewEdge at the end of the chain + * \param iViewEdge: + * The ViewEdge that must be added. + * \param orientation: + * The orientation with which this ViewEdge must be processed. + */ + void push_viewedge_back(ViewEdge *iViewEdge, bool orientation); + + /*! Adds a ViewEdge at the beginning of the chain + * \param iViewEdge: + * The ViewEdge that must be added. + * \param orientation: + * The orientation with which this ViewEdge must be processed. + */ + void push_viewedge_front(ViewEdge *iViewEdge, bool orientation); + + inline void setSplittingId(Id *sid) + { + _splittingId = sid; + } + + inline Id *getSplittingId() + { + return _splittingId; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Chain") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Chain") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_CHAIN_H__ +#endif // __FREESTYLE_CHAIN_H__ diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp index 08bdeb61713..de6c50fe571 100644 --- a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp @@ -29,93 +29,93 @@ namespace Freestyle { ViewEdge *AdjacencyIterator::operator*() { - return (*_internalIterator).first; + return (*_internalIterator).first; } bool AdjacencyIterator::isIncoming() const { - return (*_internalIterator).second; + return (*_internalIterator).second; } int AdjacencyIterator::increment() { - ++_internalIterator; - while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) - ++_internalIterator; - return 0; + ++_internalIterator; + while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) + ++_internalIterator; + return 0; } bool AdjacencyIterator::isValid(ViewEdge *edge) { - if (_restrictToSelection) { - if (edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp()) - return false; - } - if (_restrictToUnvisited) { - if (edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp()) - return false; - } - return true; + if (_restrictToSelection) { + if (edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp()) + return false; + } + if (_restrictToUnvisited) { + if (edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp()) + return false; + } + return true; } int ChainingIterator::init() { - return Director_BPy_ChainingIterator_init(this); + return Director_BPy_ChainingIterator_init(this); } int ChainingIterator::traverse(const AdjacencyIterator &it) { - return Director_BPy_ChainingIterator_traverse(this, const_cast<AdjacencyIterator &>(it)); + return Director_BPy_ChainingIterator_traverse(this, const_cast<AdjacencyIterator &>(it)); } int ChainingIterator::increment() { - _increment = true; - ViewVertex *vertex = getVertex(); - if (!vertex) { - _edge = 0; - return 0; - } - AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); - if (it.isEnd()) { - _edge = 0; - return 0; - } - if (traverse(it) < 0) - return -1; - _edge = result; - if (_edge == 0) - return 0; - if (_edge->A() == vertex) - _orientation = true; - else - _orientation = false; - return 0; + _increment = true; + ViewVertex *vertex = getVertex(); + if (!vertex) { + _edge = 0; + return 0; + } + AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); + if (it.isEnd()) { + _edge = 0; + return 0; + } + if (traverse(it) < 0) + return -1; + _edge = result; + if (_edge == 0) + return 0; + if (_edge->A() == vertex) + _orientation = true; + else + _orientation = false; + return 0; } int ChainingIterator::decrement() { - _increment = false; - ViewVertex *vertex = getVertex(); - if (!vertex) { - _edge = 0; - return 0; - } - AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); - if (it.isEnd()) { - _edge = 0; - return 0; - } - if (traverse(it) < 0) - return -1; - _edge = result; - if (_edge == 0) - return 0; - if (_edge->B() == vertex) - _orientation = true; - else - _orientation = false; - return 0; + _increment = false; + ViewVertex *vertex = getVertex(); + if (!vertex) { + _edge = 0; + return 0; + } + AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited); + if (it.isEnd()) { + _edge = 0; + return 0; + } + if (traverse(it) < 0) + return -1; + _edge = result; + if (_edge == 0) + return 0; + if (_edge->B() == vertex) + _orientation = true; + else + _orientation = false; + return 0; } // @@ -123,88 +123,88 @@ int ChainingIterator::decrement() // /////////////////////////////////////////////////////////// -int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait) +int ChainSilhouetteIterator::traverse(const AdjacencyIterator &ait) { - AdjacencyIterator it(ait); - ViewVertex *nextVertex = getVertex(); - // we can't get a NULL nextVertex here, it was intercepted before - if (nextVertex->getNature() & Nature::T_VERTEX) { - TVertex *tvertex = (TVertex *)nextVertex; - ViewEdge *mate = (tvertex)->mate(getCurrentEdge()); - while (!it.isEnd()) { - ViewEdge *ve = *it; - if (ve == mate) { - result = ve; - return 0; - } - ++it; - } - result = 0; - return 0; - } - if (nextVertex->getNature() & Nature::NON_T_VERTEX) { - //soc NonTVertex *nontvertex = (NonTVertex*)nextVertex; - ViewEdge *newEdge(0); - // we'll try to chain the edges by keeping the same nature... - // the preseance order is : SILHOUETTE, BORDER, CREASE, MATERIAL_BOUNDARY, EDGE_MARK, SUGGESTIVE, VALLEY, RIDGE - Nature::EdgeNature natures[8] = { - Nature::SILHOUETTE, - Nature::BORDER, - Nature::CREASE, - Nature::MATERIAL_BOUNDARY, - Nature::EDGE_MARK, - Nature::SUGGESTIVE_CONTOUR, - Nature::VALLEY, - Nature::RIDGE, - }; - int numNatures = sizeof(natures) / sizeof(Nature::EdgeNature); - for (int i = 0; i < numNatures; ++i) { - if (getCurrentEdge()->getNature() & natures[i]) { - int n = 0; - while (!it.isEnd()) { - ViewEdge *ve = *it; - if (ve->getNature() & natures[i]) { - ++n; - newEdge = ve; - } - ++it; - } - if (n == 1) { - result = newEdge; - } - else { - result = 0; - } - return 0; - } - } - } - result = 0; - return 0; + AdjacencyIterator it(ait); + ViewVertex *nextVertex = getVertex(); + // we can't get a NULL nextVertex here, it was intercepted before + if (nextVertex->getNature() & Nature::T_VERTEX) { + TVertex *tvertex = (TVertex *)nextVertex; + ViewEdge *mate = (tvertex)->mate(getCurrentEdge()); + while (!it.isEnd()) { + ViewEdge *ve = *it; + if (ve == mate) { + result = ve; + return 0; + } + ++it; + } + result = 0; + return 0; + } + if (nextVertex->getNature() & Nature::NON_T_VERTEX) { + //soc NonTVertex *nontvertex = (NonTVertex*)nextVertex; + ViewEdge *newEdge(0); + // we'll try to chain the edges by keeping the same nature... + // the preseance order is : SILHOUETTE, BORDER, CREASE, MATERIAL_BOUNDARY, EDGE_MARK, SUGGESTIVE, VALLEY, RIDGE + Nature::EdgeNature natures[8] = { + Nature::SILHOUETTE, + Nature::BORDER, + Nature::CREASE, + Nature::MATERIAL_BOUNDARY, + Nature::EDGE_MARK, + Nature::SUGGESTIVE_CONTOUR, + Nature::VALLEY, + Nature::RIDGE, + }; + int numNatures = sizeof(natures) / sizeof(Nature::EdgeNature); + for (int i = 0; i < numNatures; ++i) { + if (getCurrentEdge()->getNature() & natures[i]) { + int n = 0; + while (!it.isEnd()) { + ViewEdge *ve = *it; + if (ve->getNature() & natures[i]) { + ++n; + newEdge = ve; + } + ++it; + } + if (n == 1) { + result = newEdge; + } + else { + result = 0; + } + return 0; + } + } + } + result = 0; + return 0; } -int ChainPredicateIterator::traverse(const AdjacencyIterator& ait) +int ChainPredicateIterator::traverse(const AdjacencyIterator &ait) { - if (!_unary_predicate || !_binary_predicate) - return -1; - AdjacencyIterator it(ait); - // Iterates over next edges to see if one of them respects the predicate: - while (!it.isEnd()) { - ViewEdge *ve = *it; - if (_unary_predicate->operator()(*ve) < 0) - return -1; - if (_unary_predicate->result) { - if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0) - return -1; - if (_binary_predicate->result) { - result = ve; - return 0; - } - } - ++it; - } - result = 0; - return 0; + if (!_unary_predicate || !_binary_predicate) + return -1; + AdjacencyIterator it(ait); + // Iterates over next edges to see if one of them respects the predicate: + while (!it.isEnd()) { + ViewEdge *ve = *it; + if (_unary_predicate->operator()(*ve) < 0) + return -1; + if (_unary_predicate->result) { + if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0) + return -1; + if (_binary_predicate->result) { + result = ve; + return 0; + } + } + ++it; + } + result = 0; + return 0; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h index ee9730edf2b..57a73c64b3d 100644 --- a/source/blender/freestyle/intern/stroke/ChainingIterators.h +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h @@ -40,95 +40,98 @@ 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); +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); }; // @@ -144,101 +147,101 @@ protected: * 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(); +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(); }; // @@ -252,42 +255,45 @@ public: * 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; - } +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; + } }; // @@ -303,88 +309,94 @@ public: * 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; - } +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__ +#endif // __FREESTYLE_CHAINING_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp index f390b4edfb6..5609013a417 100644 --- a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp @@ -32,52 +32,52 @@ namespace ContextFunctions { unsigned GetTimeStampCF() { - return TimeStamp::instance()->getTimeStamp(); + return TimeStamp::instance()->getTimeStamp(); } unsigned GetCanvasWidthCF() { - return Canvas::getInstance()->width(); + return Canvas::getInstance()->width(); } unsigned GetCanvasHeightCF() { - return Canvas::getInstance()->height(); + return Canvas::getInstance()->height(); } BBox<Vec2i> GetBorderCF() { - return Canvas::getInstance()->border(); + return Canvas::getInstance()->border(); } void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float iSigma) { - return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels, iSigma); + return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels, iSigma); } float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y) { - Canvas *canvas = Canvas::getInstance(); - return canvas->readMapPixel(iMapName, level, x, y); + Canvas *canvas = Canvas::getInstance(); + return canvas->readMapPixel(iMapName, level, x, y); } float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - return svm->readCompleteViewMapPixel(level, x, y); + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + return svm->readCompleteViewMapPixel(level, x, y); } float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - return svm->readSteerableViewMapPixel(iOrientation, level, x, y); + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + return svm->readSteerableViewMapPixel(iOrientation, level, x, y); } FEdge *GetSelectedFEdgeCF() { - return Canvas::getInstance()->selectedFEdge(); + return Canvas::getInstance()->selectedFEdge(); } -} // ContextFunctions namespace +} // namespace ContextFunctions } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h index 190217c52f7..6897e2b193d 100644 --- a/source/blender/freestyle/intern/stroke/ContextFunctions.h +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h @@ -55,7 +55,10 @@ BBox<Vec2i> GetBorderCF(); // Load map /*! Loads an image map for further reading */ -void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels = 4, float iSigma = 1.0f); +void LoadMapCF(const char *iFileName, + const char *iMapName, + unsigned iNbLevels = 4, + float iSigma = 1.0f); // ReadMapPixel /*! Reads a pixel in a user-defined map @@ -100,8 +103,8 @@ float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, uns // DEBUG FEdge *GetSelectedFEdgeCF(); -} // end of namespace ContextFunctions +} // end of namespace ContextFunctions } /* namespace Freestyle */ -#endif // __FREESTYLE_CONTEXT_FUNCTIONS_H__ +#endif // __FREESTYLE_CONTEXT_FUNCTIONS_H__ diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp index f4439e1398c..f7309252aaf 100644 --- a/source/blender/freestyle/intern/stroke/Curve.cpp +++ b/source/blender/freestyle/intern/stroke/Curve.cpp @@ -19,7 +19,7 @@ * \brief Class to define a container for curves */ -#include <stdio.h> /* printf */ +#include <stdio.h> /* printf */ #include "Curve.h" #include "CurveIterators.h" @@ -40,455 +40,457 @@ namespace Freestyle { CurvePoint::CurvePoint() { - __A = 0; - __B = 0; - _t2d = 0; + __A = 0; + __B = 0; + _t2d = 0; } CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t) { - __A = iA; - __B = iB; - _t2d = t; - if ((iA == 0) && (t == 1.0f)) { - _Point2d = __B->point2d(); - _Point3d = __B->point3d(); - } - else if ((iB == 0) && (t == 0.0f)) { - _Point2d = __A->point2d(); - _Point3d = __A->point3d(); - } - else { - _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d()); - _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); - } + __A = iA; + __B = iB; + _t2d = t; + if ((iA == 0) && (t == 1.0f)) { + _Point2d = __B->point2d(); + _Point3d = __B->point3d(); + } + else if ((iB == 0) && (t == 0.0f)) { + _Point2d = __A->point2d(); + _Point3d = __A->point3d(); + } + else { + _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d()); + _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); + } } CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3) { - __A = 0; - __B = 0; - float t1 = iA->t2d(); - float t2 = iB->t2d(); - if ((iA->A() == iB->A()) && (iA->B() == iB->B()) && - (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0)) - { - __A = iA->A(); - __B = iB->B(); - _t2d = t1 + t2 * t3 - t1 * t3; - } - else if ((iA->B() == 0) && (iB->B() == 0)) { - __A = iA->A(); - __B = iB->A(); - _t2d = t3; - } - else if ((iA->t2d() == 0) && (iB->t2d() == 0)) { - __A = iA->A(); - __B = iB->A(); - _t2d = t3; - } - else if (iA->A() == iB->A()) { -iA_A_eq_iB_A: - if (iA->t2d() == 0) { - __A = iB->A(); - __B = iB->B(); - _t2d = t3; - } - else if (iB->t2d() == 0) { - __A = iA->A(); - __B = iA->B(); - _t2d = t3; - } - } - else if (iA->B() == iB->B()) { -iA_B_eq_iB_B: - if (iA->t2d() == 1) { - __A = iB->A(); - __B = iB->B(); - _t2d = t3; - } - else if (iB->t2d() == 1) { - __A = iA->A(); - __B = iA->B(); - _t2d = t3; - } - } - else if (iA->B() == iB->A()) { -iA_B_eq_iB_A: - if ((iA->t2d() != 1.0f) && (iB->t2d() == 0.0f)) { - __A = iA->A(); - __B = iA->B(); - _t2d = t1 + t3 - t1 * t3; - //_t2d = t3; - } - else if ((iA->t2d() == 1.0f) && (iB->t2d() != 0.0f)) { - __A = iB->A(); - __B = iB->B(); - //_t2d = t3; - _t2d = t2 * t3; - } - else if ((iA->getPoint2D() - iB->getPoint2D()).norm() < 1.0e-6) { - __A = iB->A(); - __B = iB->B(); - //_t2d = t3; - _t2d = t2 * t3; - } - } - else if (iA->A() != 0 && iB->A() != 0 && (iA->A()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) { - goto iA_A_eq_iB_A; - } - else if (iA->B() != 0 && iB->B() != 0 && (iA->B()->point3d() - iB->B()->point3d()).norm() < 1.0e-6) { - goto iA_B_eq_iB_B; - } - else if (iA->B() != 0 && iB->A() != 0 && (iA->B()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) { - goto iA_B_eq_iB_A; - } - - if (!__A || !__B) { - if (G.debug & G_DEBUG_FREESTYLE) { - printf("iA A 0x%p p (%f, %f)\n", iA->A(), iA->A()->getPoint2D().x(), iA->A()->getPoint2D().y()); - printf("iA B 0x%p p (%f, %f)\n", iA->B(), iA->B()->getPoint2D().x(), iA->B()->getPoint2D().y()); - printf("iB A 0x%p p (%f, %f)\n", iB->A(), iB->A()->getPoint2D().x(), iB->A()->getPoint2D().y()); - printf("iB B 0x%p p (%f, %f)\n", iB->B(), iB->B()->getPoint2D().x(), iB->B()->getPoint2D().y()); - printf("iA t2d %f p (%f, %f)\n", iA->t2d(), iA->getPoint2D().x(), iA->getPoint2D().y()); - printf("iB t2d %f p (%f, %f)\n", iB->t2d(), iB->getPoint2D().x(), iB->getPoint2D().y()); - } - cerr << "Fatal error in CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)" << endl; - } - BLI_assert(__A != 0 && __B != 0); + __A = 0; + __B = 0; + float t1 = iA->t2d(); + float t2 = iB->t2d(); + if ((iA->A() == iB->A()) && (iA->B() == iB->B()) && (iA->A() != 0) && (iA->B() != 0) && + (iB->A() != 0) && (iB->B() != 0)) { + __A = iA->A(); + __B = iB->B(); + _t2d = t1 + t2 * t3 - t1 * t3; + } + else if ((iA->B() == 0) && (iB->B() == 0)) { + __A = iA->A(); + __B = iB->A(); + _t2d = t3; + } + else if ((iA->t2d() == 0) && (iB->t2d() == 0)) { + __A = iA->A(); + __B = iB->A(); + _t2d = t3; + } + else if (iA->A() == iB->A()) { + iA_A_eq_iB_A: + if (iA->t2d() == 0) { + __A = iB->A(); + __B = iB->B(); + _t2d = t3; + } + else if (iB->t2d() == 0) { + __A = iA->A(); + __B = iA->B(); + _t2d = t3; + } + } + else if (iA->B() == iB->B()) { + iA_B_eq_iB_B: + if (iA->t2d() == 1) { + __A = iB->A(); + __B = iB->B(); + _t2d = t3; + } + else if (iB->t2d() == 1) { + __A = iA->A(); + __B = iA->B(); + _t2d = t3; + } + } + else if (iA->B() == iB->A()) { + iA_B_eq_iB_A: + if ((iA->t2d() != 1.0f) && (iB->t2d() == 0.0f)) { + __A = iA->A(); + __B = iA->B(); + _t2d = t1 + t3 - t1 * t3; + //_t2d = t3; + } + else if ((iA->t2d() == 1.0f) && (iB->t2d() != 0.0f)) { + __A = iB->A(); + __B = iB->B(); + //_t2d = t3; + _t2d = t2 * t3; + } + else if ((iA->getPoint2D() - iB->getPoint2D()).norm() < 1.0e-6) { + __A = iB->A(); + __B = iB->B(); + //_t2d = t3; + _t2d = t2 * t3; + } + } + else if (iA->A() != 0 && iB->A() != 0 && + (iA->A()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) { + goto iA_A_eq_iB_A; + } + else if (iA->B() != 0 && iB->B() != 0 && + (iA->B()->point3d() - iB->B()->point3d()).norm() < 1.0e-6) { + goto iA_B_eq_iB_B; + } + else if (iA->B() != 0 && iB->A() != 0 && + (iA->B()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) { + goto iA_B_eq_iB_A; + } + + if (!__A || !__B) { + if (G.debug & G_DEBUG_FREESTYLE) { + printf( + "iA A 0x%p p (%f, %f)\n", iA->A(), iA->A()->getPoint2D().x(), iA->A()->getPoint2D().y()); + printf( + "iA B 0x%p p (%f, %f)\n", iA->B(), iA->B()->getPoint2D().x(), iA->B()->getPoint2D().y()); + printf( + "iB A 0x%p p (%f, %f)\n", iB->A(), iB->A()->getPoint2D().x(), iB->A()->getPoint2D().y()); + printf( + "iB B 0x%p p (%f, %f)\n", iB->B(), iB->B()->getPoint2D().x(), iB->B()->getPoint2D().y()); + printf("iA t2d %f p (%f, %f)\n", iA->t2d(), iA->getPoint2D().x(), iA->getPoint2D().y()); + printf("iB t2d %f p (%f, %f)\n", iB->t2d(), iB->getPoint2D().x(), iB->getPoint2D().y()); + } + cerr << "Fatal error in CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)" + << endl; + } + BLI_assert(__A != 0 && __B != 0); #if 0 - _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d()); - _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); + _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d()); + _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); #endif - _Point2d = iA->point2d() + t3 * (iB->point2d() - iA->point2d()); - _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); + _Point2d = iA->point2d() + t3 * (iB->point2d() - iA->point2d()); + _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d()); } -CurvePoint::CurvePoint(const CurvePoint& iBrother) +CurvePoint::CurvePoint(const CurvePoint &iBrother) { - __A = iBrother.__A; - __B = iBrother.__B; - _t2d = iBrother._t2d; - _Point2d = iBrother._Point2d; - _Point3d = iBrother._Point3d; + __A = iBrother.__A; + __B = iBrother.__B; + _t2d = iBrother._t2d; + _Point2d = iBrother._Point2d; + _Point3d = iBrother._Point3d; } -CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother) +CurvePoint &CurvePoint::operator=(const CurvePoint &iBrother) { - __A = iBrother.__A; - __B = iBrother.__B; - _t2d = iBrother._t2d; - _Point2d = iBrother._Point2d; - _Point3d = iBrother._Point3d; - return *this; + __A = iBrother.__A; + __B = iBrother.__B; + _t2d = iBrother._t2d; + _Point2d = iBrother._Point2d; + _Point3d = iBrother._Point3d; + return *this; } - FEdge *CurvePoint::fedge() { - if (getNature() & Nature::T_VERTEX) - return 0; - return __A->fedge(); -} - - -FEdge *CurvePoint::getFEdge(Interface0D& inter) -{ - CurvePoint *iVertexB = dynamic_cast<CurvePoint*>(&inter); - if (!iVertexB) { - cerr << "Warning: CurvePoint::getFEdge() failed to cast the given 0D element to CurvePoint." << endl; - return 0; - } - if (((__A == iVertexB->__A) && (__B == iVertexB->__B)) || - ((__A == iVertexB->__B) && (__B == iVertexB->__A))) - { - return __A->getFEdge(*__B); - } - if (__B == 0) { - if (iVertexB->__B == 0) - return __A->getFEdge(*(iVertexB->__A)); - else if (iVertexB->__A == __A) - return __A->getFEdge(*(iVertexB->__B)); - else if (iVertexB->__B == __A) - return __A->getFEdge(*(iVertexB->__A)); - } - if (iVertexB->__B == 0) { - if (iVertexB->__A == __A) - return __B->getFEdge(*(iVertexB->__A)); - else if (iVertexB->__A == __B) - return __A->getFEdge(*(iVertexB->__A)); - } - if (__B == iVertexB->__A) { - if ((_t2d != 1) && (iVertexB->_t2d == 0)) - return __A->getFEdge(*__B); - if ((_t2d == 1) && (iVertexB->_t2d != 0)) - return iVertexB->__A->getFEdge(*(iVertexB->__B)); - } - if (__B == iVertexB->__B) { - if ((_t2d != 1) && (iVertexB->_t2d == 1)) - return __A->getFEdge(*__B); - if ((_t2d == 1) && (iVertexB->_t2d != 1)) - return iVertexB->__A->getFEdge(*(iVertexB->__B)); - } - if (__A == iVertexB->__A) { - if ((_t2d == 0) && (iVertexB->_t2d != 0)) - return iVertexB->__A->getFEdge(*(iVertexB->__B)); - if ((_t2d != 0) && (iVertexB->_t2d == 0)) - return __A->getFEdge(*__B); - } - if (__A == iVertexB->__B) { - if ((_t2d == 0) && (iVertexB->_t2d != 1)) - return iVertexB->__A->getFEdge(*(iVertexB->__B)); - if ((_t2d != 0) && (iVertexB->_t2d == 1)) - return __A->getFEdge(*__B); - } + if (getNature() & Nature::T_VERTEX) + return 0; + return __A->fedge(); +} + +FEdge *CurvePoint::getFEdge(Interface0D &inter) +{ + CurvePoint *iVertexB = dynamic_cast<CurvePoint *>(&inter); + if (!iVertexB) { + cerr << "Warning: CurvePoint::getFEdge() failed to cast the given 0D element to CurvePoint." + << endl; + return 0; + } + if (((__A == iVertexB->__A) && (__B == iVertexB->__B)) || + ((__A == iVertexB->__B) && (__B == iVertexB->__A))) { + return __A->getFEdge(*__B); + } + if (__B == 0) { + if (iVertexB->__B == 0) + return __A->getFEdge(*(iVertexB->__A)); + else if (iVertexB->__A == __A) + return __A->getFEdge(*(iVertexB->__B)); + else if (iVertexB->__B == __A) + return __A->getFEdge(*(iVertexB->__A)); + } + if (iVertexB->__B == 0) { + if (iVertexB->__A == __A) + return __B->getFEdge(*(iVertexB->__A)); + else if (iVertexB->__A == __B) + return __A->getFEdge(*(iVertexB->__A)); + } + if (__B == iVertexB->__A) { + if ((_t2d != 1) && (iVertexB->_t2d == 0)) + return __A->getFEdge(*__B); + if ((_t2d == 1) && (iVertexB->_t2d != 0)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + } + if (__B == iVertexB->__B) { + if ((_t2d != 1) && (iVertexB->_t2d == 1)) + return __A->getFEdge(*__B); + if ((_t2d == 1) && (iVertexB->_t2d != 1)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + } + if (__A == iVertexB->__A) { + if ((_t2d == 0) && (iVertexB->_t2d != 0)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + if ((_t2d != 0) && (iVertexB->_t2d == 0)) + return __A->getFEdge(*__B); + } + if (__A == iVertexB->__B) { + if ((_t2d == 0) && (iVertexB->_t2d != 1)) + return iVertexB->__A->getFEdge(*(iVertexB->__B)); + if ((_t2d != 0) && (iVertexB->_t2d == 1)) + return __A->getFEdge(*__B); + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - printf("__A 0x%p p (%f, %f)\n", __A, __A->getPoint2D().x(), __A->getPoint2D().y()); - printf("__B 0x%p p (%f, %f)\n", __B, __B->getPoint2D().x(), __B->getPoint2D().y()); - printf("iVertexB->A() 0x%p p (%f, %f)\n", iVertexB->A(), iVertexB->A()->getPoint2D().x(), - iVertexB->A()->getPoint2D().y()); - printf("iVertexB->B() 0x%p p (%f, %f)\n", iVertexB->B(), iVertexB->B()->getPoint2D().x(), - iVertexB->B()->getPoint2D().y()); - printf("_t2d %f p (%f, %f)\n", _t2d, getPoint2D().x(), getPoint2D().y()); - printf("iVertexB->t2d() %f p (%f, %f)\n", iVertexB->t2d(), iVertexB->getPoint2D().x(), - iVertexB->getPoint2D().y()); - } + if (G.debug & G_DEBUG_FREESTYLE) { + printf("__A 0x%p p (%f, %f)\n", __A, __A->getPoint2D().x(), __A->getPoint2D().y()); + printf("__B 0x%p p (%f, %f)\n", __B, __B->getPoint2D().x(), __B->getPoint2D().y()); + printf("iVertexB->A() 0x%p p (%f, %f)\n", iVertexB->A(), iVertexB->A()->getPoint2D().x(), + iVertexB->A()->getPoint2D().y()); + printf("iVertexB->B() 0x%p p (%f, %f)\n", iVertexB->B(), iVertexB->B()->getPoint2D().x(), + iVertexB->B()->getPoint2D().y()); + printf("_t2d %f p (%f, %f)\n", _t2d, getPoint2D().x(), getPoint2D().y()); + printf("iVertexB->t2d() %f p (%f, %f)\n", iVertexB->t2d(), iVertexB->getPoint2D().x(), + iVertexB->getPoint2D().y()); + } #endif - cerr << "Warning: CurvePoint::getFEdge() failed." << endl; + cerr << "Warning: CurvePoint::getFEdge() failed." << endl; - return NULL; + return NULL; } - Vec3r CurvePoint::normal() const { - if (__B == 0) - return __A->normal(); - if (__A == 0) - return __B->normal(); - Vec3r Na = __A->normal(); - if (Exception::getException()) - Na = Vec3r(0, 0, 0); - Vec3r Nb = __B->normal(); - if (Exception::getException()) - Nb = Vec3r(0, 0, 0); - // compute t3d: - real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B), _t2d); - return ((1 - t3d) * Na + t3d * Nb); + if (__B == 0) + return __A->normal(); + if (__A == 0) + return __B->normal(); + Vec3r Na = __A->normal(); + if (Exception::getException()) + Na = Vec3r(0, 0, 0); + Vec3r Nb = __B->normal(); + if (Exception::getException()) + Nb = Vec3r(0, 0, 0); + // compute t3d: + real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B), _t2d); + return ((1 - t3d) * Na + t3d * Nb); } - #if 0 Material CurvePoint::material() const { - if (__A == 0) - return __B->material(); - return __A->material(); + if (__A == 0) + return __B->material(); + return __A->material(); } Id CurvePoint::shape_id() const { - if (__A == 0) - return __B->shape_id(); - return __A->shape_id(); + if (__A == 0) + return __B->shape_id(); + return __A->shape_id(); } #endif - const SShape *CurvePoint::shape() const { - if (__A == 0) - return __B->shape(); - return __A->shape(); + if (__A == 0) + return __B->shape(); + return __A->shape(); } #if 0 float CurvePoint::shape_importance() const { - if (__A == 0) - return __B->shape_importance(); - return __A->shape_importance(); + if (__A == 0) + return __B->shape_importance(); + return __A->shape_importance(); } const unsigned CurvePoint::qi() const { - if (__A == 0) - return __B->qi(); - if (__B == 0) - return __A->qi(); - return __A->getFEdge(*__B)->qi(); + if (__A == 0) + return __B->qi(); + if (__B == 0) + return __A->qi(); + return __A->getFEdge(*__B)->qi(); } #endif occluder_container::const_iterator CurvePoint::occluders_begin() const { - if (__A == 0) - return __B->occluders_begin(); - if (__B == 0) - return __A->occluders_begin(); - return __A->getFEdge(*__B)->occluders_begin(); + if (__A == 0) + return __B->occluders_begin(); + if (__B == 0) + return __A->occluders_begin(); + return __A->getFEdge(*__B)->occluders_begin(); } occluder_container::const_iterator CurvePoint::occluders_end() const { - if (__A == 0) - return __B->occluders_end(); - if (__B == 0) - return __A->occluders_end(); - return __A->getFEdge(*__B)->occluders_end(); + if (__A == 0) + return __B->occluders_end(); + if (__B == 0) + return __A->occluders_end(); + return __A->getFEdge(*__B)->occluders_end(); } bool CurvePoint::occluders_empty() const { - if (__A == 0) - return __B->occluders_empty(); - if (__B == 0) - return __A->occluders_empty(); - return __A->getFEdge(*__B)->occluders_empty(); + if (__A == 0) + return __B->occluders_empty(); + if (__B == 0) + return __A->occluders_empty(); + return __A->getFEdge(*__B)->occluders_empty(); } int CurvePoint::occluders_size() const { - if (__A == 0) - return __B->occluders_size(); - if (__B == 0) - return __A->occluders_size(); - return __A->getFEdge(*__B)->occluders_size(); + if (__A == 0) + return __B->occluders_size(); + if (__B == 0) + return __A->occluders_size(); + return __A->getFEdge(*__B)->occluders_size(); } const SShape *CurvePoint::occluded_shape() const { - if (__A == 0) - return __B->occluded_shape(); - if (__B == 0) - return __A->occluded_shape(); - return __A->getFEdge(*__B)->occluded_shape(); + if (__A == 0) + return __B->occluded_shape(); + if (__B == 0) + return __A->occluded_shape(); + return __A->getFEdge(*__B)->occluded_shape(); } -const Polygon3r& CurvePoint::occludee() const +const Polygon3r &CurvePoint::occludee() const { - if (__A == 0) - return __B->occludee(); - if (__B == 0) - return __A->occludee(); - return __A->getFEdge(*__B)->occludee(); + if (__A == 0) + return __B->occludee(); + if (__B == 0) + return __A->occludee(); + return __A->getFEdge(*__B)->occludee(); } -const bool CurvePoint::occludee_empty() const +const bool CurvePoint::occludee_empty() const { - if (__A == 0) - return __B->occludee_empty(); - if (__B == 0) - return __A->occludee_empty(); - return __A->getFEdge(*__B)->occludee_empty(); + if (__A == 0) + return __B->occludee_empty(); + if (__B == 0) + return __A->occludee_empty(); + return __A->getFEdge(*__B)->occludee_empty(); } real CurvePoint::z_discontinuity() const { - if (__A == 0) - return __B->z_discontinuity(); - if (__B == 0) - return __A->z_discontinuity(); - if (__A->getFEdge(*__B) == 0) - return 0.0; + if (__A == 0) + return __B->z_discontinuity(); + if (__B == 0) + return __A->z_discontinuity(); + if (__A->getFEdge(*__B) == 0) + return 0.0; - return __A->getFEdge(*__B)->z_discontinuity(); + return __A->getFEdge(*__B)->z_discontinuity(); } #if 0 float CurvePoint::local_average_depth() const { - return local_average_depth_function<CurvePoint >(this); + return local_average_depth_function<CurvePoint >(this); } float CurvePoint::local_depth_variance() const { - return local_depth_variance_function<CurvePoint >(this); + return local_depth_variance_function<CurvePoint >(this); } real CurvePoint::local_average_density(float sigma) const { - //return local_average_density<CurvePoint >(this); - return density_function<CurvePoint >(this); + //return local_average_density<CurvePoint >(this); + return density_function<CurvePoint >(this); } Vec3r shaded_color() const; Vec3r CurvePoint::orientation2d() const { - if (__A == 0) - return __B->orientation2d(); - if (__B == 0) - return __A->orientation2d(); - return __B->point2d() - __A->point2d(); + if (__A == 0) + return __B->orientation2d(); + if (__B == 0) + return __A->orientation2d(); + return __B->point2d() - __A->point2d(); } Vec3r CurvePoint::orientation3d() const { - if (__A == 0) - return __B->orientation3d(); - if (__B == 0) - return __A->orientation3d(); - return __B->point3d() - __A->point3d(); + if (__A == 0) + return __B->orientation3d(); + if (__B == 0) + return __A->orientation3d(); + return __B->point3d() - __A->point3d(); } real curvature2d() const { - return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); + return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); } Vec3r CurvePoint::curvature2d_as_vector() const { -#if 0 - Vec3r edgeA = (_FEdges[0])->orientation2d().normalize(); - Vec3r edgeB = (_FEdges[1])->orientation2d().normalize(); - return edgeA + edgeB; -#endif - if (__A == 0) - return __B->curvature2d_as_vector(); - if (__B == 0) - return __A->curvature2d_as_vector(); - return ((1 - _t2d) * __A->curvature2d_as_vector() + _t2d * __B->curvature2d_as_vector()); +# if 0 + Vec3r edgeA = (_FEdges[0])->orientation2d().normalize(); + Vec3r edgeB = (_FEdges[1])->orientation2d().normalize(); + return edgeA + edgeB; +# endif + if (__A == 0) + return __B->curvature2d_as_vector(); + if (__B == 0) + return __A->curvature2d_as_vector(); + return ((1 - _t2d) * __A->curvature2d_as_vector() + _t2d * __B->curvature2d_as_vector()); } real CurvePoint::curvature2d_as_angle() const { -#if 0 - Vec3r edgeA = (_FEdges[0])->orientation2d(); - Vec3r edgeB = (_FEdges[1])->orientation2d(); - Vec2d N1(-edgeA.y(), edgeA.x()); - N1.normalize(); - Vec2d N2(-edgeB.y(), edgeB.x()); - N2.normalize(); - return acos((N1 * N2)); -#endif - if (__A == 0) - return __B->curvature2d_as_angle(); - if (__B == 0) - return __A->curvature2d_as_angle(); - return ((1 - _t2d) * __A->curvature2d_as_angle() + _t2d * __B->curvature2d_as_angle()); +# if 0 + Vec3r edgeA = (_FEdges[0])->orientation2d(); + Vec3r edgeB = (_FEdges[1])->orientation2d(); + Vec2d N1(-edgeA.y(), edgeA.x()); + N1.normalize(); + Vec2d N2(-edgeB.y(), edgeB.x()); + N2.normalize(); + return acos((N1 * N2)); +# endif + if (__A == 0) + return __B->curvature2d_as_angle(); + if (__B == 0) + return __A->curvature2d_as_angle(); + return ((1 - _t2d) * __A->curvature2d_as_angle() + _t2d * __B->curvature2d_as_angle()); } real CurvePoint::curvatureFredo() const { - if (__A == 0) - return __B->curvatureFredo(); - if (__B == 0) - return __A->curvatureFredo(); - return ((1 - _t2d) * __A->curvatureFredo() + _t2d * __B->curvatureFredo()); + if (__A == 0) + return __B->curvatureFredo(); + if (__B == 0) + return __A->curvatureFredo(); + return ((1 - _t2d) * __A->curvatureFredo() + _t2d * __B->curvatureFredo()); } Vec2d CurvePoint::directionFredo () const { - if (__A == 0) - return __B->directionFredo(); - if (__B == 0) - return __A->directionFredo(); - return ((1 - _t2d) * __A->directionFredo() + _t2d * __B->directionFredo()); + if (__A == 0) + return __B->directionFredo(); + if (__B == 0) + return __A->directionFredo(); + return ((1 - _t2d) * __A->directionFredo() + _t2d * __B->directionFredo()); } #endif @@ -504,122 +506,166 @@ Vec2d CurvePoint::directionFredo () const Curve::~Curve() { - if (!_Vertices.empty()) { - for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; ++it) { - delete (*it); - } - _Vertices.clear(); - } + if (!_Vertices.empty()) { + for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; + ++it) { + delete (*it); + } + _Vertices.clear(); + } } /*! iterators access */ Curve::point_iterator Curve::points_begin(float step) { - vertex_container::iterator second = _Vertices.begin(); - ++second; - return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.0f, 0.0f); - //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f); + vertex_container::iterator second = _Vertices.begin(); + ++second; + return point_iterator( + _Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.0f, 0.0f); + //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f); } Curve::const_point_iterator Curve::points_begin(float step) const { - vertex_container::const_iterator second = _Vertices.begin(); - ++second; - return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), - _nSegments, step, 0.0f, 0.0f); - //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f); + vertex_container::const_iterator second = _Vertices.begin(); + ++second; + return const_point_iterator( + _Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.0f, 0.0f); + //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f); } Curve::point_iterator Curve::points_end(float step) { - return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), - _nSegments, step, 1.0f, _Length); - //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length); + return point_iterator(_Vertices.end(), + _Vertices.end(), + _Vertices.begin(), + _Vertices.end(), + _nSegments, + step, + 1.0f, + _Length); + //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length); } Curve::const_point_iterator Curve::points_end(float step) const { - return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), - _nSegments, step, 1.0f, _Length); - //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length); + return const_point_iterator(_Vertices.end(), + _Vertices.end(), + _Vertices.begin(), + _Vertices.end(), + _nSegments, + step, + 1.0f, + _Length); + //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length); } // Adavnced Iterators access Curve::point_iterator Curve::vertices_begin() { - return points_begin(0); + return points_begin(0); } Curve::const_point_iterator Curve::vertices_begin() const { - return points_begin(0); + return points_begin(0); } Curve::point_iterator Curve::vertices_end() { - return points_end(0); + return points_end(0); } Curve::const_point_iterator Curve::vertices_end() const { - return points_end(0); + return points_end(0); } // specialized iterators access CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t) { - vertex_container::iterator second = _Vertices.begin(); - ++second; - return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), - 0, _nSegments, _Length, t, 0.0f, 0.0f); + vertex_container::iterator second = _Vertices.begin(); + ++second; + return CurveInternal::CurvePointIterator(_Vertices.begin(), + second, + _Vertices.begin(), + _Vertices.end(), + 0, + _nSegments, + _Length, + t, + 0.0f, + 0.0f); } CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t) { - vertex_container::iterator last = _Vertices.end(); - --last; - return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), - _nSegments, _nSegments, _Length, t, 0.0f, _Length); + vertex_container::iterator last = _Vertices.end(); + --last; + return CurveInternal::CurvePointIterator(last, + _Vertices.end(), + _Vertices.begin(), + _Vertices.end(), + _nSegments, + _nSegments, + _Length, + t, + 0.0f, + _Length); } -CurveInternal::CurvePointIterator Curve::curveVerticesBegin() +CurveInternal::CurvePointIterator Curve::curveVerticesBegin() { - return curvePointsBegin(0); + return curvePointsBegin(0); } CurveInternal::CurvePointIterator Curve::curveVerticesEnd() { - return curvePointsEnd(0); + return curvePointsEnd(0); } Interface0DIterator Curve::pointsBegin(float t) { - vertex_container::iterator second = _Vertices.begin(); - ++second; - Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), - _Vertices.end(), 0, _nSegments, _Length, - t, 0.0f, 0.0f)); - return ret; + vertex_container::iterator second = _Vertices.begin(); + ++second; + Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), + second, + _Vertices.begin(), + _Vertices.end(), + 0, + _nSegments, + _Length, + t, + 0.0f, + 0.0f)); + return ret; } Interface0DIterator Curve::pointsEnd(float t) { - vertex_container::iterator last = _Vertices.end(); - --last; - Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), - _Vertices.end(), _nSegments, _nSegments, - _Length, t, 0.0f, _Length)); - return ret; + vertex_container::iterator last = _Vertices.end(); + --last; + Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, + _Vertices.end(), + _Vertices.begin(), + _Vertices.end(), + _nSegments, + _nSegments, + _Length, + t, + 0.0f, + _Length)); + return ret; } Interface0DIterator Curve::verticesBegin() { - return pointsBegin(0); + return pointsBegin(0); } Interface0DIterator Curve::verticesEnd() { - return pointsEnd(0); + return pointsEnd(0); } #if 0 @@ -627,188 +673,188 @@ Vec3r shaded_color(int iCombination = 0) const; Vec3r Curve::orientation2d(point_iterator it) const { - return (*it)->orientation2d(); + return (*it)->orientation2d(); } template <class BaseVertex> Vec3r Curve::orientation2d(int iCombination) const { - return edge_orientation2d_function<Curve >(this, iCombination); + return edge_orientation2d_function<Curve >(this, iCombination); } Vec3r Curve::orientation3d(point_iterator it) const { - return (*it)->orientation3d(); + return (*it)->orientation3d(); } Vec3r Curve::orientation3d(int iCombination) const { - return edge_orientation3d_function<Curve >(this, iCombination); + return edge_orientation3d_function<Curve >(this, iCombination); } real curvature2d(point_iterator it) const { - return (*it)->curvature2d(); + return (*it)->curvature2d(); } real curvature2d(int iCombination = 0) const; Material Curve::material() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - const Material& mat = (*v)->material(); - for (; v != vend; ++v) { - if ((*v)->material() != mat) - Exception::raiseException(); - } - return mat; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + const Material& mat = (*v)->material(); + for (; v != vend; ++v) { + if ((*v)->material() != mat) + Exception::raiseException(); + } + return mat; } int Curve::qi() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - int qi_ = (*v)->qi(); - for (; v != vend; ++v) { - if ((*v)->qi() != qi_) - Exception::raiseException(); - } - return qi_; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + int qi_ = (*v)->qi(); + for (; v != vend; ++v) { + if ((*v)->qi() != qi_) + Exception::raiseException(); + } + return qi_; } occluder_container::const_iterator occluders_begin() const { - return _FEdgeA->occluders().begin(); + return _FEdgeA->occluders().begin(); } occluder_container::const_iterator occluders_end() const { - return _FEdgeA->occluders().end(); + return _FEdgeA->occluders().end(); } int Curve::occluders_size() const { - return qi(); + return qi(); } bool Curve::occluders_empty() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - bool empty = (*v)->occluders_empty(); - for (; v != vend; ++v) { - if ((*v)->occluders_empty() != empty) - Exception::raiseException(); - } - return empty; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + bool empty = (*v)->occluders_empty(); + for (; v != vend; ++v) { + if ((*v)->occluders_empty() != empty) + Exception::raiseException(); + } + return empty; } const Polygon3r& occludee() const { - return *(_FEdgeA->aFace()); + return *(_FEdgeA->aFace()); } const SShape *Curve::occluded_shape() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - const SShape *sshape = (*v)->occluded_shape(); - for (; v != vend; ++v) { - if ((*v)->occluded_shape() != sshape) - Exception::raiseException(); - } - return sshape; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + const SShape *sshape = (*v)->occluded_shape(); + for (; v != vend; ++v) { + if ((*v)->occluded_shape() != sshape) + Exception::raiseException(); + } + return sshape; } const bool Curve::occludee_empty() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - bool empty = (*v)->occludee_empty(); - for (; v != vend; ++v) { - if ((*v)->occludee_empty() != empty) - Exception::raiseException(); - } - return empty; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + bool empty = (*v)->occludee_empty(); + for (; v != vend; ++v) { + if ((*v)->occludee_empty() != empty) + Exception::raiseException(); + } + return empty; } real Curve::z_discontinuity(int iCombination) const { - return z_discontinuity_edge_function<Curve>(this, iCombination); + return z_discontinuity_edge_function<Curve>(this, iCombination); } int Curve::shape_id() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - Id id = (*v)->shape_id(); - for (; v != vend; ++v) { - if ((*v)->shape_id() != id) - Exception::raiseException(); - } - return id.first; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + Id id = (*v)->shape_id(); + for (; v != vend; ++v) { + if ((*v)->shape_id() != id) + Exception::raiseException(); + } + return id.first; } const SShape *Curve::shape() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - const SShape *sshape = (*v)->shape(); - for (; v != vend; ++v) { - if ((*v)->shape() != sshape) - Exception::raiseException(); - } - return sshape; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + const SShape *sshape = (*v)->shape(); + for (; v != vend; ++v) { + if ((*v)->shape() != sshape) + Exception::raiseException(); + } + return sshape; } occluder_container::const_iterator Curve::occluders_begin() const { - const_vertex_iterator v = vertices_begin(); - return (*v)->occluders_begin(); + const_vertex_iterator v = vertices_begin(); + return (*v)->occluders_begin(); } occluder_container::const_iterator Curve::occluders_end() const { - const_vertex_iterator v = vertices_end(); - return (*v)->occluders_end(); + const_vertex_iterator v = vertices_end(); + return (*v)->occluders_end(); } Vec3r Curve::curvature2d_as_vector(int iCombination) const { - return curvature2d_as_vector_edge_function<Curve>(this, iCombination); + return curvature2d_as_vector_edge_function<Curve>(this, iCombination); } real Curve::curvature2d_as_angle(int iCombination) const { - return curvature2d_as_angle_edge_function<Curve>(this, iCombination); + return curvature2d_as_angle_edge_function<Curve>(this, iCombination); } float Curve::shape_importance(int iCombination) const { - return shape_importance_edge_function<Curve>(this, iCombination); + return shape_importance_edge_function<Curve>(this, iCombination); } float Curve::local_average_depth(int iCombination) const { - return local_average_depth_edge_function<Curve>(this, iCombination); + return local_average_depth_edge_function<Curve>(this, iCombination); } float Curve::local_depth_variance(int iCombination ) const { - return local_depth_variance_edge_function<Curve>(this, iCombination); -#if 0 - local_depth_variance_functor<Point> functor; - float result; - Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result); - return result; -#endif + return local_depth_variance_edge_function<Curve>(this, iCombination); +# if 0 + local_depth_variance_functor<Point> functor; + float result; + Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result); + return result; +# endif } real Curve::local_average_density(float sigma, int iCombination ) const { - return density_edge_function<Curve>(this, iCombination); -#if 0 - density_functor<Point> functor; - real result; - Evaluate<real, density_functor<Point> >(&functor, iCombination, result); - return result; -#endif + return density_edge_function<Curve>(this, iCombination); +# if 0 + density_functor<Point> functor; + real result; + Evaluate<real, density_functor<Point> >(&functor, iCombination, result); + return result; +# endif } /* UNUSED */ @@ -816,109 +862,109 @@ real Curve::local_average_density(float sigma, int iCombination ) const void Curve::computeCurvatureAndOrientation () { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(), v2, prevV, v0; - Vec2d p0, p1, p2; - Vec3r p; - - p = (*v)->point2d(); - p0 = Vec2d(p[0], p[1]); - prevV = v; - ++v; - p = (*v)->point2d(); - p1 = Vec2d(p[0], p[1]); - Vec2d prevDir(p1 - p0); - - for (; v! = vend; ++v) { - v2 = v; - ++v2; - if (v2 == vend) - break; - Vec3r p2 = (*v2)->point2d(); - - Vec2d BA = p0 - p1; - Vec2d BC = p2 - p1; - real lba = BA.norm(), lbc = BC.norm(); - BA.normalizeSafe(); - BC.normalizeSafe(); - Vec2d normalCurvature = BA + BC; - Vec2d dir = Vec2d(BC - BA); - Vec2d normal = Vec2d(-dir[1], dir[0]); - - normal.normalizeSafe(); - real curvature = normalCurvature * normal; - if (lba + lbc > MY_EPSILON) - curvature /= (0.5 * lba + lbc); - if (dir.norm() < MY_EPSILON) - dir = 0.1 * prevDir; - (*v)->setCurvatureFredo(curvature); - (*v)->setDirectionFredo(dir); - - prevV = v; - p0 = p1; - p1 = p2; - prevDir = dir; - prevDir.normalize(); - } - (*v)->setCurvatureFredo((*prevV)->curvatureFredo()); - (*v)->setDirectionFredo((*v)->point2d() - (*prevV)->point2d()); - v0 = vertices_begin(); - v2 = v0; - ++v2; - (*v0)->setCurvatureFredo((*v2)->curvatureFredo()); - (*v0)->setDirectionFredo((*v2)->point2d() - (*v0)->point2d()); - - //closed curve case one day... - - // - return; - - //numerical degeneracy verification... we'll see later - const_vertex_iterator vLastReliable = vertices_begin(); - - v = vertices_begin(); - p = (*v)->point2d(); - p0 = Vec2d(p[0], p[1]); - prevV = v; - ++v; - p = (*v)->point2d(); - p1 = Vec2d(p[0], p[1]); - bool isReliable = false; - if ((p1 - p0).norm > EPS_CURVA) { - vLastReliable = v; - isReliable = true; - } - - for (; v != vend; ++v) { - v2 = v; - ++v2; - if (v2 == vend) - break; - Vec3r p2 = (*v2)->point2d(); - - Vec2d BA = p0 - p1; - Vec2d BC = p2 - p1; - real lba = BA.norm(), lbc = BC.norm(); - - if ((lba + lbc) < EPS_CURVA) { - isReliable = false; - cerr << "/"; - } - else { - if (!isReliable) { //previous points were not reliable - const_vertex_iterator vfix = vLastReliable; - ++vfix; - for (; vfix != v; ++vfix) { - (*vfix)->setCurvatureFredo((*v)->curvatureFredo()); - (*vfix)->setDirectionFredo((*v)->directionFredo()); - } - } - isReliable = true; - vLastReliable = v; - } - prevV = v; - p0 = p1; - p1 = p2; - } + const_vertex_iterator v = vertices_begin(), vend = vertices_end(), v2, prevV, v0; + Vec2d p0, p1, p2; + Vec3r p; + + p = (*v)->point2d(); + p0 = Vec2d(p[0], p[1]); + prevV = v; + ++v; + p = (*v)->point2d(); + p1 = Vec2d(p[0], p[1]); + Vec2d prevDir(p1 - p0); + + for (; v! = vend; ++v) { + v2 = v; + ++v2; + if (v2 == vend) + break; + Vec3r p2 = (*v2)->point2d(); + + Vec2d BA = p0 - p1; + Vec2d BC = p2 - p1; + real lba = BA.norm(), lbc = BC.norm(); + BA.normalizeSafe(); + BC.normalizeSafe(); + Vec2d normalCurvature = BA + BC; + Vec2d dir = Vec2d(BC - BA); + Vec2d normal = Vec2d(-dir[1], dir[0]); + + normal.normalizeSafe(); + real curvature = normalCurvature * normal; + if (lba + lbc > MY_EPSILON) + curvature /= (0.5 * lba + lbc); + if (dir.norm() < MY_EPSILON) + dir = 0.1 * prevDir; + (*v)->setCurvatureFredo(curvature); + (*v)->setDirectionFredo(dir); + + prevV = v; + p0 = p1; + p1 = p2; + prevDir = dir; + prevDir.normalize(); + } + (*v)->setCurvatureFredo((*prevV)->curvatureFredo()); + (*v)->setDirectionFredo((*v)->point2d() - (*prevV)->point2d()); + v0 = vertices_begin(); + v2 = v0; + ++v2; + (*v0)->setCurvatureFredo((*v2)->curvatureFredo()); + (*v0)->setDirectionFredo((*v2)->point2d() - (*v0)->point2d()); + + //closed curve case one day... + + // + return; + + //numerical degeneracy verification... we'll see later + const_vertex_iterator vLastReliable = vertices_begin(); + + v = vertices_begin(); + p = (*v)->point2d(); + p0 = Vec2d(p[0], p[1]); + prevV = v; + ++v; + p = (*v)->point2d(); + p1 = Vec2d(p[0], p[1]); + bool isReliable = false; + if ((p1 - p0).norm > EPS_CURVA) { + vLastReliable = v; + isReliable = true; + } + + for (; v != vend; ++v) { + v2 = v; + ++v2; + if (v2 == vend) + break; + Vec3r p2 = (*v2)->point2d(); + + Vec2d BA = p0 - p1; + Vec2d BC = p2 - p1; + real lba = BA.norm(), lbc = BC.norm(); + + if ((lba + lbc) < EPS_CURVA) { + isReliable = false; + cerr << "/"; + } + else { + if (!isReliable) { //previous points were not reliable + const_vertex_iterator vfix = vLastReliable; + ++vfix; + for (; vfix != v; ++vfix) { + (*vfix)->setCurvatureFredo((*v)->curvatureFredo()); + (*vfix)->setDirectionFredo((*v)->directionFredo()); + } + } + isReliable = true; + vLastReliable = v; + } + prevV = v; + p0 = p1; + p1 = p2; + } } #endif diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h index 40c20fb777c..234f9df0e48 100644 --- a/source/blender/freestyle/intern/stroke/Curve.h +++ b/source/blender/freestyle/intern/stroke/Curve.h @@ -36,7 +36,7 @@ #include "../system/BaseIterator.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -60,288 +60,288 @@ using namespace Geometry; * Thus, a CurvePoint is built by lineraly interpolating two SVertex. * CurvePoint can be used as virtual points while querying 0D information along a curve at a given resolution. */ -class CurvePoint : public Interface0D -{ -public: // Implementation of Interface0D - /*! Returns the string "CurvePoint"*/ - virtual string getExactTypeName() const - { - return "CurvePoint"; - } - - // Data access methods - /*! Returns the 3D X coordinate of the point */ - virtual real getX() const - { - return _Point3d.x(); - } - - /*! Returns the 3D Y coordinate of the point */ - virtual real getY() const - { - return _Point3d.y(); - } - - /*! Returns the 3D Z coordinate of the point */ - virtual real getZ() const - { - return _Point3d.z(); - } - - /*! Returns the 3D point. */ - virtual Vec3r getPoint3D() const - { - return _Point3d; - } - - /*! Returns the projected 3D X coordinate of the point */ - virtual real getProjectedX() const - { - return _Point2d.x(); - } - - /*! Returns the projected 3D Y coordinate of the point */ - virtual real getProjectedY() const - { - return _Point2d.y(); - } - - /*! Returns the projected 3D Z coordinate of the point */ - virtual real getProjectedZ() const - { - return _Point2d.z(); - } - - /*! Returns the 2D point. */ - virtual Vec2r getPoint2D() const - { - return Vec2r(_Point2d.x(), _Point2d.y()); - } - - virtual FEdge *getFEdge(Interface0D& inter); - - /*! Returns the CurvePoint's Id */ - virtual Id getId() const - { - Id id; - if (_t2d == 0) - return __A->getId(); - else if (_t2d == 1) - return __B->getId(); - return id; - } - - /*! Returns the CurvePoint's Nature */ - virtual Nature::VertexNature getNature() const - { - Nature::VertexNature nature = Nature::POINT; - if (_t2d == 0) - nature |= __A->getNature(); - else if (_t2d == 1) - nature |= __B->getNature(); - return nature; - } - - /*! Cast the Interface0D in SVertex if it can be. */ - virtual SVertex *castToSVertex() - { - if (_t2d == 0) - return __A; - else if (_t2d == 1) - return __B; - return Interface0D::castToSVertex(); - } - - /*! Cast the Interface0D in ViewVertex if it can be. */ - virtual ViewVertex *castToViewVertex() - { - if (_t2d == 0) - return __A->castToViewVertex(); - else if (_t2d == 1) - return __B->castToViewVertex(); - return Interface0D::castToViewVertex(); - } - - /*! Cast the Interface0D in NonTVertex if it can be. */ - virtual NonTVertex *castToNonTVertex() - { - if (_t2d == 0) - return __A->castToNonTVertex(); - else if (_t2d == 1) - return __B->castToNonTVertex(); - return Interface0D::castToNonTVertex(); - } - - /*! Cast the Interface0D in TVertex if it can be. */ - virtual TVertex *castToTVertex() - { - if (_t2d == 0) - return __A->castToTVertex(); - else if (_t2d == 1) - return __B->castToTVertex(); - return Interface0D::castToTVertex(); - } - -public: - typedef SVertex vertex_type; - -protected: - SVertex *__A; - SVertex *__B; - float _t2d; - //float _t3d; - Vec3r _Point2d; - Vec3r _Point3d; - -public: - /*! Defult Constructor. */ - CurvePoint(); - - /*! Builds a CurvePoint from two SVertex and an interpolation parameter. - * \param iA: - * The first SVertex - * \param iB: - * The second SVertex - * \param t2d: - * A 2D interpolation parameter used to linearly interpolate \a iA and \a iB - */ - CurvePoint(SVertex *iA, SVertex *iB, float t2d); - - /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter. - * \param iA: - * The first CurvePoint - * \param iB: - * The second CurvePoint - * \param t2d: - * The 2D interpolation parameter used to linearly interpolate \a iA and \a iB. - */ - CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d); - - //CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d); - - /*! Copy Constructor. */ - CurvePoint(const CurvePoint& iBrother); - - /*! Operator = */ - CurvePoint& operator=(const CurvePoint& iBrother); - - /*! Destructor */ - virtual ~CurvePoint() {} - - /*! Operator == */ - bool operator==(const CurvePoint& b) - { - return ((__A == b.__A) && (__B == b.__B) && (_t2d == b._t2d)); - } - - /* accessors */ - /*! Returns the first SVertex upon which the CurvePoint is built. */ - inline SVertex *A() - { - return __A; - } - - /*! Returns the second SVertex upon which the CurvePoint is built. */ - inline SVertex *B() - { - return __B; - } - - /*! Returns the interpolation parameter. */ - inline float t2d() const - { - return _t2d; - } +class CurvePoint : public Interface0D { + public: // Implementation of Interface0D + /*! Returns the string "CurvePoint"*/ + virtual string getExactTypeName() const + { + return "CurvePoint"; + } + + // Data access methods + /*! Returns the 3D X coordinate of the point */ + virtual real getX() const + { + return _Point3d.x(); + } + + /*! Returns the 3D Y coordinate of the point */ + virtual real getY() const + { + return _Point3d.y(); + } + + /*! Returns the 3D Z coordinate of the point */ + virtual real getZ() const + { + return _Point3d.z(); + } + + /*! Returns the 3D point. */ + virtual Vec3r getPoint3D() const + { + return _Point3d; + } + + /*! Returns the projected 3D X coordinate of the point */ + virtual real getProjectedX() const + { + return _Point2d.x(); + } + + /*! Returns the projected 3D Y coordinate of the point */ + virtual real getProjectedY() const + { + return _Point2d.y(); + } + + /*! Returns the projected 3D Z coordinate of the point */ + virtual real getProjectedZ() const + { + return _Point2d.z(); + } + + /*! Returns the 2D point. */ + virtual Vec2r getPoint2D() const + { + return Vec2r(_Point2d.x(), _Point2d.y()); + } + + virtual FEdge *getFEdge(Interface0D &inter); + + /*! Returns the CurvePoint's Id */ + virtual Id getId() const + { + Id id; + if (_t2d == 0) + return __A->getId(); + else if (_t2d == 1) + return __B->getId(); + return id; + } + + /*! Returns the CurvePoint's Nature */ + virtual Nature::VertexNature getNature() const + { + Nature::VertexNature nature = Nature::POINT; + if (_t2d == 0) + nature |= __A->getNature(); + else if (_t2d == 1) + nature |= __B->getNature(); + return nature; + } + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex *castToSVertex() + { + if (_t2d == 0) + return __A; + else if (_t2d == 1) + return __B; + return Interface0D::castToSVertex(); + } + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex *castToViewVertex() + { + if (_t2d == 0) + return __A->castToViewVertex(); + else if (_t2d == 1) + return __B->castToViewVertex(); + return Interface0D::castToViewVertex(); + } + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex *castToNonTVertex() + { + if (_t2d == 0) + return __A->castToNonTVertex(); + else if (_t2d == 1) + return __B->castToNonTVertex(); + return Interface0D::castToNonTVertex(); + } + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex *castToTVertex() + { + if (_t2d == 0) + return __A->castToTVertex(); + else if (_t2d == 1) + return __B->castToTVertex(); + return Interface0D::castToTVertex(); + } + + public: + typedef SVertex vertex_type; + + protected: + SVertex *__A; + SVertex *__B; + float _t2d; + //float _t3d; + Vec3r _Point2d; + Vec3r _Point3d; + + public: + /*! Defult Constructor. */ + CurvePoint(); + + /*! Builds a CurvePoint from two SVertex and an interpolation parameter. + * \param iA: + * The first SVertex + * \param iB: + * The second SVertex + * \param t2d: + * A 2D interpolation parameter used to linearly interpolate \a iA and \a iB + */ + CurvePoint(SVertex *iA, SVertex *iB, float t2d); + + /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter. + * \param iA: + * The first CurvePoint + * \param iB: + * The second CurvePoint + * \param t2d: + * The 2D interpolation parameter used to linearly interpolate \a iA and \a iB. + */ + CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d); + + //CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d); + + /*! Copy Constructor. */ + CurvePoint(const CurvePoint &iBrother); + + /*! Operator = */ + CurvePoint &operator=(const CurvePoint &iBrother); + + /*! Destructor */ + virtual ~CurvePoint() + { + } + + /*! Operator == */ + bool operator==(const CurvePoint &b) + { + return ((__A == b.__A) && (__B == b.__B) && (_t2d == b._t2d)); + } + + /* accessors */ + /*! Returns the first SVertex upon which the CurvePoint is built. */ + inline SVertex *A() + { + return __A; + } + + /*! Returns the second SVertex upon which the CurvePoint is built. */ + inline SVertex *B() + { + return __B; + } + + /*! Returns the interpolation parameter. */ + inline float t2d() const + { + return _t2d; + } #if 0 - inline const float t3d() const - { - return _t3d; - } + inline const float t3d() const + { + return _t3d; + } #endif - /* modifiers */ - /*! Sets the first SVertex upon which to build the CurvePoint. */ - inline void setA(SVertex *iA) - { - __A = iA; - } - - /*! Sets the second SVertex upon which to build the CurvePoint. */ - inline void setB(SVertex *iB) - { - __B = iB; - } - - /*! Sets the 2D interpolation parameter to use. */ - inline void setT2d(float t) - { - _t2d = t; - } + /* modifiers */ + /*! Sets the first SVertex upon which to build the CurvePoint. */ + inline void setA(SVertex *iA) + { + __A = iA; + } + + /*! Sets the second SVertex upon which to build the CurvePoint. */ + inline void setB(SVertex *iB) + { + __B = iB; + } + + /*! Sets the 2D interpolation parameter to use. */ + inline void setT2d(float t) + { + _t2d = t; + } #if 0 - inline void SetT3d(float t) - { - _t3d = t; - } + inline void SetT3d(float t) + { + _t3d = t; + } #endif - /* Information access interface */ - - FEdge *fedge(); - - inline const Vec3r& point2d() const - { - return _Point2d; - } - - inline const Vec3r& point3d() const - { - return _Point3d; - } - - Vec3r normal() const; - //FrsMaterial material() const; - //Id shape_id() const; - const SShape *shape() const; - //float shape_importance() const; - - //const unsigned qi() const; - occluder_container::const_iterator occluders_begin() const; - occluder_container::const_iterator occluders_end() const; - bool occluders_empty() const; - int occluders_size() const; - const Polygon3r& occludee() const; - const SShape *occluded_shape() const; - const bool occludee_empty() const; - real z_discontinuity() const; + /* Information access interface */ + + FEdge *fedge(); + + inline const Vec3r &point2d() const + { + return _Point2d; + } + + inline const Vec3r &point3d() const + { + return _Point3d; + } + + Vec3r normal() const; + //FrsMaterial material() const; + //Id shape_id() const; + const SShape *shape() const; + //float shape_importance() const; + + //const unsigned qi() const; + occluder_container::const_iterator occluders_begin() const; + occluder_container::const_iterator occluders_end() const; + bool occluders_empty() const; + int occluders_size() const; + const Polygon3r &occludee() const; + const SShape *occluded_shape() const; + const bool occludee_empty() const; + real z_discontinuity() const; #if 0 - float local_average_depth() const; - float local_depth_variance() const; - real local_average_density(float sigma = 2.3f) const; - Vec3r shaded_color() const; - Vec3r orientation2d() const; - Vec3r orientation3d() const; - - real curvature2d() const - { - return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); - } - - Vec3r curvature2d_as_vector() const; - /*! angle in radians */ - real curvature2d_as_angle() const; - - real curvatureFredo() const; - Vec2d directionFredo() const; + float local_average_depth() const; + float local_depth_variance() const; + real local_average_density(float sigma = 2.3f) const; + Vec3r shaded_color() const; + Vec3r orientation2d() const; + Vec3r orientation3d() const; + + real curvature2d() const + { + return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); + } + + Vec3r curvature2d_as_vector() const; + /*! angle in radians */ + real curvature2d_as_angle() const; + + real curvatureFredo() const; + Vec2d directionFredo() const; #endif #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:CurvePoint") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:CurvePoint") #endif }; - /**********************************/ /* */ /* */ @@ -357,236 +357,237 @@ class CurvePoint_nonconst_traits; template<class Traits> class __point_iterator; class CurvePointIterator; -} // end of namespace CurveInternal +} // end of namespace CurveInternal /*! Base class for curves made of CurvePoints. * SVertex is the type of the initial curve vertices. * A Chain is a specialization of a Curve. */ -class Curve : public Interface1D -{ -public: - typedef CurvePoint Vertex; - typedef CurvePoint Point; - typedef Point point_type; - typedef Vertex vertex_type; - typedef deque<Vertex*> vertex_container; - - /* Iterator to iterate over a vertex edges */ - - typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits > point_iterator; - typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits > const_point_iterator; - typedef point_iterator vertex_iterator ; - typedef const_point_iterator const_vertex_iterator ; - -protected: - vertex_container _Vertices; - double _Length; - Id _Id; - unsigned _nSegments; // number of segments - -public: - /*! Default Constructor. */ - Curve() - { - _Length = 0; - _Id = 0; - _nSegments = 0; - } - - /*! Builds a Curve from its id */ - Curve(const Id& id) - { - _Length = 0; - _Id = id; - _nSegments = 0; - } - - /*! Copy Constructor. */ - Curve(const Curve& iBrother) - { - _Length = iBrother._Length; - _Vertices = iBrother._Vertices; - _Id = iBrother._Id; - _nSegments = 0; - } - - /*! Destructor. */ - virtual ~Curve(); - - /*! Returns the string "Curve" */ - virtual string getExactTypeName() const - { - return "Curve"; - } +class Curve : public Interface1D { + public: + typedef CurvePoint Vertex; + typedef CurvePoint Point; + typedef Point point_type; + typedef Vertex vertex_type; + typedef deque<Vertex *> vertex_container; + + /* Iterator to iterate over a vertex edges */ + + typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits> + point_iterator; + typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits> + const_point_iterator; + typedef point_iterator vertex_iterator; + typedef const_point_iterator const_vertex_iterator; + + protected: + vertex_container _Vertices; + double _Length; + Id _Id; + unsigned _nSegments; // number of segments + + public: + /*! Default Constructor. */ + Curve() + { + _Length = 0; + _Id = 0; + _nSegments = 0; + } + + /*! Builds a Curve from its id */ + Curve(const Id &id) + { + _Length = 0; + _Id = id; + _nSegments = 0; + } + + /*! Copy Constructor. */ + Curve(const Curve &iBrother) + { + _Length = iBrother._Length; + _Vertices = iBrother._Vertices; + _Id = iBrother._Id; + _nSegments = 0; + } + + /*! Destructor. */ + virtual ~Curve(); + + /*! Returns the string "Curve" */ + virtual string getExactTypeName() const + { + return "Curve"; + } #if 0 - /* fredo's curvature storage */ - void computeCurvatureAndOrientation(); + /* fredo's curvature storage */ + void computeCurvatureAndOrientation(); #endif - /*! Adds a single vertex (CurvePoint) at the end of the Curve */ - inline void push_vertex_back(Vertex *iVertex) - { - if (!_Vertices.empty()) { - Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); - _Length += vec_tmp.norm(); - ++_nSegments; - } - Vertex *new_vertex = new Vertex(*iVertex); - _Vertices.push_back(new_vertex); - } - - /*! Adds a single vertex (SVertex) at the end of the Curve */ - inline void push_vertex_back(SVertex *iVertex) - { - if (!_Vertices.empty()) { - Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); - _Length += vec_tmp.norm(); - ++_nSegments; - } - Vertex *new_vertex = new Vertex(iVertex, 0, 0); - _Vertices.push_back(new_vertex); - } - - /*! Adds a single vertex (CurvePoint) at the front of the Curve */ - inline void push_vertex_front(Vertex *iVertex) - { - if (!_Vertices.empty()) { - Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); - _Length += vec_tmp.norm(); - ++_nSegments; - } - Vertex *new_vertex = new Vertex(*iVertex); - _Vertices.push_front(new_vertex); - } - - /*! Adds a single vertex (SVertex) at the front of the Curve */ - inline void push_vertex_front(SVertex *iVertex) - { - if (!_Vertices.empty()) { - Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); - _Length += vec_tmp.norm(); - ++_nSegments; - } - Vertex *new_vertex = new Vertex(iVertex, 0, 0); - _Vertices.push_front(new_vertex); - } - - /*! Returns true is the Curve doesn't have any Vertex yet. */ - inline bool empty() const - { - return _Vertices.empty(); - } - - /*! Returns the 2D length of the Curve. */ - inline real getLength2D() const - { - return _Length; - } - - /*! Returns the Id of the 1D element. */ - virtual Id getId() const - { - return _Id; - } - - /*! Returns the number of segments in the polyline constituting the Curve. */ - inline unsigned int nSegments() const - { - return _nSegments; - } - - inline void setId(const Id& id) - { - _Id = id; - } - - /* Information access interface */ + /*! Adds a single vertex (CurvePoint) at the end of the Curve */ + inline void push_vertex_back(Vertex *iVertex) + { + if (!_Vertices.empty()) { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(*iVertex); + _Vertices.push_back(new_vertex); + } + + /*! Adds a single vertex (SVertex) at the end of the Curve */ + inline void push_vertex_back(SVertex *iVertex) + { + if (!_Vertices.empty()) { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(iVertex, 0, 0); + _Vertices.push_back(new_vertex); + } + + /*! Adds a single vertex (CurvePoint) at the front of the Curve */ + inline void push_vertex_front(Vertex *iVertex) + { + if (!_Vertices.empty()) { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(*iVertex); + _Vertices.push_front(new_vertex); + } + + /*! Adds a single vertex (SVertex) at the front of the Curve */ + inline void push_vertex_front(SVertex *iVertex) + { + if (!_Vertices.empty()) { + Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d()); + _Length += vec_tmp.norm(); + ++_nSegments; + } + Vertex *new_vertex = new Vertex(iVertex, 0, 0); + _Vertices.push_front(new_vertex); + } + + /*! Returns true is the Curve doesn't have any Vertex yet. */ + inline bool empty() const + { + return _Vertices.empty(); + } + + /*! Returns the 2D length of the Curve. */ + inline real getLength2D() const + { + return _Length; + } + + /*! Returns the Id of the 1D element. */ + virtual Id getId() const + { + return _Id; + } + + /*! Returns the number of segments in the polyline constituting the Curve. */ + inline unsigned int nSegments() const + { + return _nSegments; + } + + inline void setId(const Id &id) + { + _Id = id; + } + + /* Information access interface */ #if 0 - inline Vec3r shaded_color(int iCombination = 0) const; - inline Vec3r orientation2d(point_iterator it) const; - Vec3r orientation2d(int iCombination = 0) const; - Vec3r orientation3d(point_iterator it) const; - Vec3r orientation3d(int iCombination = 0) const; - - real curvature2d(point_iterator it) const - { - return (*it)->curvature2d(); - } - - real curvature2d(int iCombination = 0) const; - FrsMaterial material() const; - int qi() const; - occluder_container::const_iterator occluders_begin() const; - occluder_container::const_iterator occluders_end() const; - int occluders_size() const; - bool occluders_empty() const; - - const Polygon3r& occludee() const - { - return *(_FEdgeA->aFace()); - } - - const SShape *occluded_shape() const; - const bool occludee_empty() const; - real z_discontinuity(int iCombination = 0) const; - int shape_id() const; - const SShape *shape() const; - float shape_importance(int iCombination = 0) const; - float local_average_depth(int iCombination = 0) const; - float local_depth_variance(int iCombination = 0) const; - real local_average_density(float sigma = 2.3f, int iCombination = 0) const; - Vec3r curvature2d_as_vector(int iCombination = 0) const; - /*! angle in radians */ - real curvature2d_as_angle(int iCombination = 0) const; + inline Vec3r shaded_color(int iCombination = 0) const; + inline Vec3r orientation2d(point_iterator it) const; + Vec3r orientation2d(int iCombination = 0) const; + Vec3r orientation3d(point_iterator it) const; + Vec3r orientation3d(int iCombination = 0) const; + + real curvature2d(point_iterator it) const + { + return (*it)->curvature2d(); + } + + real curvature2d(int iCombination = 0) const; + FrsMaterial material() const; + int qi() const; + occluder_container::const_iterator occluders_begin() const; + occluder_container::const_iterator occluders_end() const; + int occluders_size() const; + bool occluders_empty() const; + + const Polygon3r& occludee() const + { + return *(_FEdgeA->aFace()); + } + + const SShape *occluded_shape() const; + const bool occludee_empty() const; + real z_discontinuity(int iCombination = 0) const; + int shape_id() const; + const SShape *shape() const; + float shape_importance(int iCombination = 0) const; + float local_average_depth(int iCombination = 0) const; + float local_depth_variance(int iCombination = 0) const; + real local_average_density(float sigma = 2.3f, int iCombination = 0) const; + Vec3r curvature2d_as_vector(int iCombination = 0) const; + /*! angle in radians */ + real curvature2d_as_angle(int iCombination = 0) const; #endif - /* advanced iterators access */ - point_iterator points_begin(float step = 0); - const_point_iterator points_begin(float step = 0) const; - point_iterator points_end(float step = 0); - const_point_iterator points_end(float step = 0) const; - - /* methods given for convenience */ - point_iterator vertices_begin(); - const_point_iterator vertices_begin() const; - point_iterator vertices_end(); - const_point_iterator vertices_end() const; - - // specialized iterators access - CurveInternal::CurvePointIterator curvePointsBegin(float t = 0.0f); - CurveInternal::CurvePointIterator curvePointsEnd(float t = 0.0f); - - CurveInternal::CurvePointIterator curveVerticesBegin(); - CurveInternal::CurvePointIterator curveVerticesEnd(); - - // Iterators access - /*! Returns an Interface0DIterator pointing onto the first vertex of the Curve and that can iterate - * over the \a vertices of the Curve. - */ - virtual Interface0DIterator verticesBegin(); - - /*! Returns an Interface0DIterator pointing after the last vertex of the Curve and that can iterate - * over the \a vertices of the Curve. - */ - virtual Interface0DIterator verticesEnd(); - - /*! Returns an Interface0DIterator pointing onto the first point of the Curve and that can iterate - * over the \a points of the Curve at any resolution. - * At each iteration a virtual temporary CurvePoint is created. - */ - virtual Interface0DIterator pointsBegin(float t = 0.0f); - - /*! Returns an Interface0DIterator pointing after the last point of the Curve and that can iterate - * over the \a points of the Curve at any resolution. - * At each iteration a virtual temporary CurvePoint is created. - */ - virtual Interface0DIterator pointsEnd(float t = 0.0f); + /* advanced iterators access */ + point_iterator points_begin(float step = 0); + const_point_iterator points_begin(float step = 0) const; + point_iterator points_end(float step = 0); + const_point_iterator points_end(float step = 0) const; + + /* methods given for convenience */ + point_iterator vertices_begin(); + const_point_iterator vertices_begin() const; + point_iterator vertices_end(); + const_point_iterator vertices_end() const; + + // specialized iterators access + CurveInternal::CurvePointIterator curvePointsBegin(float t = 0.0f); + CurveInternal::CurvePointIterator curvePointsEnd(float t = 0.0f); + + CurveInternal::CurvePointIterator curveVerticesBegin(); + CurveInternal::CurvePointIterator curveVerticesEnd(); + + // Iterators access + /*! Returns an Interface0DIterator pointing onto the first vertex of the Curve and that can iterate + * over the \a vertices of the Curve. + */ + virtual Interface0DIterator verticesBegin(); + + /*! Returns an Interface0DIterator pointing after the last vertex of the Curve and that can iterate + * over the \a vertices of the Curve. + */ + virtual Interface0DIterator verticesEnd(); + + /*! Returns an Interface0DIterator pointing onto the first point of the Curve and that can iterate + * over the \a points of the Curve at any resolution. + * At each iteration a virtual temporary CurvePoint is created. + */ + virtual Interface0DIterator pointsBegin(float t = 0.0f); + + /*! Returns an Interface0DIterator pointing after the last point of the Curve and that can iterate + * over the \a points of the Curve at any resolution. + * At each iteration a virtual temporary CurvePoint is created. + */ + virtual Interface0DIterator pointsEnd(float t = 0.0f); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Curve") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Curve") #endif }; diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h index 0a56e674936..3cd55facd15 100644 --- a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h +++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h @@ -28,20 +28,18 @@ namespace Freestyle { namespace CurveInternal { -class CurvePoint_const_traits : public Const_traits<CurvePoint*> -{ -public: - typedef deque<CurvePoint*> vertex_container; - typedef vertex_container::const_iterator vertex_container_iterator; - typedef SVertex vertex_type; +class CurvePoint_const_traits : public Const_traits<CurvePoint *> { + public: + typedef deque<CurvePoint *> vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator; + typedef SVertex vertex_type; }; -class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint*> -{ -public: - typedef deque<CurvePoint*> vertex_container; - typedef vertex_container::iterator vertex_container_iterator; - typedef SVertex vertex_type; +class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint *> { + public: + typedef deque<CurvePoint *> vertex_container; + typedef vertex_container::iterator vertex_container_iterator; + typedef SVertex vertex_type; }; /**********************************/ @@ -52,323 +50,327 @@ public: /* */ /**********************************/ - /*! iterator on a curve. Allows an iterating outside initial vertices. A CurvePoint is instanciated an returned * when the iterator is dereferenced. */ template<class Traits> -class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> -{ -public: - typedef __point_iterator <Traits> Self; - typedef typename Traits::vertex_container_iterator vertex_container_iterator; - typedef typename Traits::vertex_type vertex_type; - typedef CurvePoint Point; - typedef Point point_type; - - typedef __point_iterator<CurvePoint_nonconst_traits> iterator; - typedef __point_iterator<CurvePoint_const_traits> const_iterator; +class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> { + public: + typedef __point_iterator<Traits> Self; + typedef typename Traits::vertex_container_iterator vertex_container_iterator; + typedef typename Traits::vertex_type vertex_type; + typedef CurvePoint Point; + typedef Point point_type; + + typedef __point_iterator<CurvePoint_nonconst_traits> iterator; + typedef __point_iterator<CurvePoint_const_traits> const_iterator; #if 0 - typedef Vertex vertex_type ; - typedef vertex_container_iterator vertex_iterator_type; - typedef CurvePoint<Vertex> Point; - typedef Point point_type; + typedef Vertex vertex_type ; + typedef vertex_container_iterator vertex_iterator_type; + typedef CurvePoint<Vertex> Point; + typedef Point point_type; #endif - typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; + typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; #if 0 -#if defined(__GNUC__) && (__GNUC__ < 3) - typedef bidirectional_iterator<CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator; -#else - typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator; -#endif +# if defined(__GNUC__) && (__GNUC__ < 3) + typedef bidirectional_iterator<CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator; +# else + typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator; +# endif #endif - friend class Curve; + friend class Curve; #if 0 - friend class Curve::vertex_iterator; - friend class __point_iterator<CurvePoint_nonconst_traits>; - friend class iterator; + friend class Curve::vertex_iterator; + friend class __point_iterator<CurvePoint_nonconst_traits>; + friend class iterator; #endif -//protected: -public: - float _CurvilinearLength; - float _step; - vertex_container_iterator __A; - vertex_container_iterator __B; - vertex_container_iterator _begin; - vertex_container_iterator _end; - int _n; - int _currentn; - float _t; - mutable Point *_Point; - -public: - inline __point_iterator(float step = 0.0f) : parent_class() - { - _step = step; - _CurvilinearLength = 0.0f; - _t = 0.0f; - _Point = 0; - _n = 0; - _currentn = 0; - } - - inline __point_iterator(const iterator& iBrother) : parent_class() - { - __A = iBrother.__A; - __B = iBrother.__B; - _begin = iBrother._begin; - _end = iBrother._end; - _CurvilinearLength = iBrother._CurvilinearLength; - _step = iBrother._step; - _t = iBrother._t; - if (iBrother._Point == 0) - _Point = 0; - else - _Point = new Point(*(iBrother._Point)); - _n = iBrother._n; - _currentn = iBrother._currentn; - } - - inline __point_iterator(const const_iterator& iBrother) : parent_class() - { - __A = iBrother.__A; - __B = iBrother.__B; - _begin = iBrother._begin; - _end = iBrother._end; - _CurvilinearLength = iBrother._CurvilinearLength; - _step = iBrother._step; - _t = iBrother._t; - if (iBrother._Point == 0) - _Point = 0; - else - _Point = new Point(*(iBrother._Point)); - _n = iBrother._n; - _currentn = iBrother._currentn; - } - - inline Self& operator=(const Self& iBrother) - { - //((bidirectional_point_iterator*)this)->operator=(iBrother); - __A = iBrother.__A; - __B = iBrother.__B; - _begin = iBrother._begin; - _end = iBrother._end; - _CurvilinearLength = iBrother._CurvilinearLength; - _step = iBrother._step; - _t = iBrother._t; - if (iBrother._Point == 0) - _Point = 0; - else - _Point = new Point(*(iBrother._Point)); - _n = iBrother._n; - _currentn = iBrother._currentn; - return *this; - } - - virtual ~__point_iterator() - { - if (_Point != 0) - delete _Point; - } - -//protected: //FIXME -public: - inline __point_iterator(vertex_container_iterator iA, vertex_container_iterator iB, - vertex_container_iterator ibegin, vertex_container_iterator iend, - int currentn, int n, float step, float t = 0.0f, float iCurvilinearLength = 0.0f) - : parent_class() - { - __A = iA; - __B = iB; - _begin = ibegin; - _end = iend; - _CurvilinearLength = iCurvilinearLength; - _step = step; - _t = t; - _Point = 0; - _n = n; - _currentn = currentn; - } - -public: - // operators - inline Self& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - - /* Operator corresponding to i++, i.e. it returns the value *and then* increments. - * That’s why we store the value in a temp. - */ - inline Self operator++(int) - { - Self tmp = *this; - increment(); - return tmp; - } - - inline Self& operator--() // operator corresponding to --i - { - decrement(); - return *this; - } - - inline Self operator--(int) // operator corresponding to i-- - { - Self tmp = *this; - decrement(); - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - return ((__A != b.__A) || (__B != b.__B) || (_t != b._t)); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual typename Traits::reference operator*() const - { - if (_Point != 0) { - delete _Point; - _Point = 0; - } - if ((_currentn < 0) || (_currentn >= _n)) - return _Point; // 0 in this case - return (_Point = new Point(*__A, *__B, _t)); - } - - virtual typename Traits::pointer operator->() const - { - return &(operator*()); - } - - virtual bool begin() const - { - if ((__A == _begin) && (_t < (float)M_EPSILON)) - return true; - return false; - } - - virtual bool end() const - { - if ((__B == _end)) - return true; - return false; - } - -protected: - virtual void increment() - { - if (_Point != 0) { - delete _Point; - _Point = 0; - } - if ((_currentn == _n - 1) && (_t == 1.0f)) { - // we're setting the iterator to end - ++__A; - ++__B; - ++_currentn; - _t = 0.0f; - return; - } - - if (0 == _step) { // means we iterate over initial vertices - Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); - _CurvilinearLength += vec_tmp.norm(); - if (_currentn == _n - 1) { - _t = 1.0f; - return; - } - ++__B; - ++__A; - ++_currentn; - return; - } - - // compute the new position: - Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); - float normAB = vec_tmp2.norm(); - - if (normAB > M_EPSILON) { - _CurvilinearLength += _step; - _t = _t + _step / normAB; - } - else { - _t = 1.0f; // AB is a null segment, we're directly at its end - } - //if normAB ~= 0, we don't change these values - if (_t >= 1) { - _CurvilinearLength -= normAB * (_t - 1); - if (_currentn == _n - 1) { - _t = 1.0f; - } - else { - _t = 0.0f; - ++_currentn; - ++__A; - ++__B; - } - } - } - - virtual void decrement() - { - if (_Point != 0) { - delete _Point; - _Point = 0; - } - - if (_t == 0.0f) { // we're at the beginning of the edge - _t = 1.0f; - --_currentn; - --__A; - --__B; - if (_currentn == _n - 1) - return; - } - - if (0 == _step) { // means we iterate over initial vertices - Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); - _CurvilinearLength -= vec_tmp.norm(); - _t = 0; - return; - } - - // compute the new position: - Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); - float normAB = vec_tmp2.norm(); - - if (normAB >M_EPSILON) { - _CurvilinearLength -= _step; - _t = _t - _step / normAB; - } - else { - _t = -1.0f; // We just need a negative value here - } - - // round value - if (fabs(_t) < (float)M_EPSILON) - _t = 0.0f; - if (_t < 0) { - if (_currentn == 0) - _CurvilinearLength = 0.0f; - else - _CurvilinearLength += normAB * (-_t); - _t = 0.0f; - } - } + //protected: + public: + float _CurvilinearLength; + float _step; + vertex_container_iterator __A; + vertex_container_iterator __B; + vertex_container_iterator _begin; + vertex_container_iterator _end; + int _n; + int _currentn; + float _t; + mutable Point *_Point; + + public: + inline __point_iterator(float step = 0.0f) : parent_class() + { + _step = step; + _CurvilinearLength = 0.0f; + _t = 0.0f; + _Point = 0; + _n = 0; + _currentn = 0; + } + + inline __point_iterator(const iterator &iBrother) : parent_class() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if (iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + } + + inline __point_iterator(const const_iterator &iBrother) : parent_class() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if (iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + } + + inline Self &operator=(const Self &iBrother) + { + //((bidirectional_point_iterator*)this)->operator=(iBrother); + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + if (iBrother._Point == 0) + _Point = 0; + else + _Point = new Point(*(iBrother._Point)); + _n = iBrother._n; + _currentn = iBrother._currentn; + return *this; + } + + virtual ~__point_iterator() + { + if (_Point != 0) + delete _Point; + } + + //protected: //FIXME + public: + inline __point_iterator(vertex_container_iterator iA, + vertex_container_iterator iB, + vertex_container_iterator ibegin, + vertex_container_iterator iend, + int currentn, + int n, + float step, + float t = 0.0f, + float iCurvilinearLength = 0.0f) + : parent_class() + { + __A = iA; + __B = iB; + _begin = ibegin; + _end = iend; + _CurvilinearLength = iCurvilinearLength; + _step = step; + _t = t; + _Point = 0; + _n = n; + _currentn = currentn; + } + + public: + // operators + inline Self &operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + + /* Operator corresponding to i++, i.e. it returns the value *and then* increments. + * That’s why we store the value in a temp. + */ + inline Self operator++(int) + { + Self tmp = *this; + increment(); + return tmp; + } + + inline Self &operator--() // operator corresponding to --i + { + decrement(); + return *this; + } + + inline Self operator--(int) // operator corresponding to i-- + { + Self tmp = *this; + decrement(); + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + return ((__A != b.__A) || (__B != b.__B) || (_t != b._t)); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual typename Traits::reference operator*() const + { + if (_Point != 0) { + delete _Point; + _Point = 0; + } + if ((_currentn < 0) || (_currentn >= _n)) + return _Point; // 0 in this case + return (_Point = new Point(*__A, *__B, _t)); + } + + virtual typename Traits::pointer operator->() const + { + return &(operator*()); + } + + virtual bool begin() const + { + if ((__A == _begin) && (_t < (float)M_EPSILON)) + return true; + return false; + } + + virtual bool end() const + { + if ((__B == _end)) + return true; + return false; + } + + protected: + virtual void increment() + { + if (_Point != 0) { + delete _Point; + _Point = 0; + } + if ((_currentn == _n - 1) && (_t == 1.0f)) { + // we're setting the iterator to end + ++__A; + ++__B; + ++_currentn; + _t = 0.0f; + return; + } + + if (0 == _step) { // means we iterate over initial vertices + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength += vec_tmp.norm(); + if (_currentn == _n - 1) { + _t = 1.0f; + return; + } + ++__B; + ++__A; + ++_currentn; + return; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = vec_tmp2.norm(); + + if (normAB > M_EPSILON) { + _CurvilinearLength += _step; + _t = _t + _step / normAB; + } + else { + _t = 1.0f; // AB is a null segment, we're directly at its end + } + //if normAB ~= 0, we don't change these values + if (_t >= 1) { + _CurvilinearLength -= normAB * (_t - 1); + if (_currentn == _n - 1) { + _t = 1.0f; + } + else { + _t = 0.0f; + ++_currentn; + ++__A; + ++__B; + } + } + } + + virtual void decrement() + { + if (_Point != 0) { + delete _Point; + _Point = 0; + } + + if (_t == 0.0f) { // we're at the beginning of the edge + _t = 1.0f; + --_currentn; + --__A; + --__B; + if (_currentn == _n - 1) + return; + } + + if (0 == _step) { // means we iterate over initial vertices + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength -= vec_tmp.norm(); + _t = 0; + return; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = vec_tmp2.norm(); + + if (normAB > M_EPSILON) { + _CurvilinearLength -= _step; + _t = _t - _step / normAB; + } + else { + _t = -1.0f; // We just need a negative value here + } + + // round value + if (fabs(_t) < (float)M_EPSILON) + _t = 0.0f; + if (_t < 0) { + if (_currentn == 0) + _CurvilinearLength = 0.0f; + else + _CurvilinearLength += normAB * (-_t); + _t = 0.0f; + } + } }; -} // end of namespace CurveInternal +} // end of namespace CurveInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__ +#endif // __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/CurveIterators.h b/source/blender/freestyle/intern/stroke/CurveIterators.h index 7b13abf9c0f..428ea022dfd 100644 --- a/source/blender/freestyle/intern/stroke/CurveIterators.h +++ b/source/blender/freestyle/intern/stroke/CurveIterators.h @@ -34,260 +34,267 @@ namespace CurveInternal { * when the iterator is dereferenced. */ -class CurvePointIterator : public Interface0DIteratorNested -{ -public: - friend class Freestyle::Curve; - -public: - float _CurvilinearLength; - float _step; - Curve::vertex_container::iterator __A; - Curve::vertex_container::iterator __B; - Curve::vertex_container::iterator _begin; - Curve::vertex_container::iterator _end; - int _n; - int _currentn; - float _t; - mutable CurvePoint _Point; - float _CurveLength; - -public: - inline CurvePointIterator(float step = 0.0f) : Interface0DIteratorNested() - { - _step = step; - _CurvilinearLength = 0.0f; - _t = 0.0f; - //_Point = 0; - _n = 0; - _currentn = 0; - _CurveLength = 0; - } - - inline CurvePointIterator(const CurvePointIterator& iBrother) : Interface0DIteratorNested() - { - __A = iBrother.__A; - __B = iBrother.__B; - _begin = iBrother._begin; - _end = iBrother._end; - _CurvilinearLength = iBrother._CurvilinearLength; - _step = iBrother._step; - _t = iBrother._t; - _Point = iBrother._Point; - _n = iBrother._n; - _currentn = iBrother._currentn; - _CurveLength = iBrother._CurveLength; - } - - inline CurvePointIterator& operator=(const CurvePointIterator& iBrother) - { - __A = iBrother.__A; - __B = iBrother.__B; - _begin = iBrother._begin; - _end = iBrother._end; - _CurvilinearLength = iBrother._CurvilinearLength; - _step = iBrother._step; - _t = iBrother._t; - _Point = iBrother._Point; - _n = iBrother._n; - _currentn = iBrother._currentn; - _CurveLength = iBrother._CurveLength; - return *this; - } - - virtual ~CurvePointIterator() {} - -protected: - inline CurvePointIterator(Curve::vertex_container::iterator iA, Curve::vertex_container::iterator iB, - Curve::vertex_container::iterator ibegin, Curve::vertex_container::iterator iend, - int currentn, int n, float iCurveLength, float step, float t = 0.0f, - float iCurvilinearLength = 0.0f) - : Interface0DIteratorNested() - { - __A = iA; - __B = iB; - _begin = ibegin; - _end = iend; - _CurvilinearLength = iCurvilinearLength; - _step = step; - _t = t; - _n = n; - _currentn = currentn; - _CurveLength = iCurveLength; - } - -public: - virtual CurvePointIterator *copy() const - { - return new CurvePointIterator(*this); - } - - inline Interface0DIterator castToInterface0DIterator() const - { - Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this)); - return ret; - } - - virtual string getExactTypeName() const - { - return "CurvePointIterator"; - } - - // operators - inline CurvePointIterator& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - - inline CurvePointIterator& operator--() // operator corresponding to --i - { - decrement(); - return *this; - } - - // comparibility - virtual bool operator==(const Interface0DIteratorNested& b) const - { - const CurvePointIterator *it_exact = dynamic_cast<const CurvePointIterator*>(&b); - if (!it_exact) - return false; - return ((__A == it_exact->__A) && (__B == it_exact->__B) && (_t == it_exact->_t)); - } - - // dereferencing - virtual CurvePoint& operator*() - { - return (_Point = CurvePoint(*__A, *__B, _t)); - } - - virtual CurvePoint *operator->() - { - return &(operator*()); - } - - virtual bool isBegin() const - { - if ((__A == _begin) && (_t < (float)M_EPSILON)) - return true; - return false; - } - - virtual bool isEnd() const - { - if (__B == _end) - return true; - return false; - } - -//protected: - virtual int increment() - { - if ((_currentn == _n - 1) && (_t == 1.0f)) { - // we're setting the iterator to end - ++__A; - ++__B; - ++_currentn; - _t = 0.0f; - return 0; - } - - if (0 == _step) { // means we iterate over initial vertices - Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); - _CurvilinearLength += (float)vec_tmp.norm(); - if (_currentn == _n - 1) { - _t = 1.0f; - return 0; - } - ++__B; - ++__A; - ++_currentn; - return 0; - } - - // compute the new position: - Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); - float normAB = (float)vec_tmp2.norm(); - - if (normAB > M_EPSILON) { - _CurvilinearLength += _step; - _t = _t + _step / normAB; - } - else { - _t = 1.0f; // AB is a null segment, we're directly at its end - } - //if normAB ~= 0, we don't change these values - if (_t >= 1) { - _CurvilinearLength -= normAB * (_t - 1); - if (_currentn == _n - 1) { - _t = 1.0f; - } - else { - _t = 0.0f; - ++_currentn; - ++__A; - ++__B; - } - } - return 0; - } - - virtual int decrement() - { - if (_t == 0.0f) { //we're at the beginning of the edge - _t = 1.0f; - --_currentn; - --__A; - --__B; - if (_currentn == _n - 1) - return 0; - } - - if (0 == _step) { // means we iterate over initial vertices - Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); - _CurvilinearLength -= (float)vec_tmp.norm(); - _t = 0; - return 0; - } - - // compute the new position: - Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); - float normAB = (float)vec_tmp2.norm(); - - if (normAB > M_EPSILON) { - _CurvilinearLength -= _step; - _t = _t - _step / normAB; - } - else { - _t = -1.0f; // We just need a negative value here - } - - // round value - if (fabs(_t) < (float)M_EPSILON) - _t = 0.0f; - if (_t < 0) { - if (_currentn == 0) - _CurvilinearLength = 0.0f; - else - _CurvilinearLength += normAB * (-_t); - _t = 0.0f; - } - return 0; - } - - virtual float t() const - { - return _CurvilinearLength; - } - - virtual float u() const - { - return _CurvilinearLength / _CurveLength; - } +class CurvePointIterator : public Interface0DIteratorNested { + public: + friend class Freestyle::Curve; + + public: + float _CurvilinearLength; + float _step; + Curve::vertex_container::iterator __A; + Curve::vertex_container::iterator __B; + Curve::vertex_container::iterator _begin; + Curve::vertex_container::iterator _end; + int _n; + int _currentn; + float _t; + mutable CurvePoint _Point; + float _CurveLength; + + public: + inline CurvePointIterator(float step = 0.0f) : Interface0DIteratorNested() + { + _step = step; + _CurvilinearLength = 0.0f; + _t = 0.0f; + //_Point = 0; + _n = 0; + _currentn = 0; + _CurveLength = 0; + } + + inline CurvePointIterator(const CurvePointIterator &iBrother) : Interface0DIteratorNested() + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + _Point = iBrother._Point; + _n = iBrother._n; + _currentn = iBrother._currentn; + _CurveLength = iBrother._CurveLength; + } + + inline CurvePointIterator &operator=(const CurvePointIterator &iBrother) + { + __A = iBrother.__A; + __B = iBrother.__B; + _begin = iBrother._begin; + _end = iBrother._end; + _CurvilinearLength = iBrother._CurvilinearLength; + _step = iBrother._step; + _t = iBrother._t; + _Point = iBrother._Point; + _n = iBrother._n; + _currentn = iBrother._currentn; + _CurveLength = iBrother._CurveLength; + return *this; + } + + virtual ~CurvePointIterator() + { + } + + protected: + inline CurvePointIterator(Curve::vertex_container::iterator iA, + Curve::vertex_container::iterator iB, + Curve::vertex_container::iterator ibegin, + Curve::vertex_container::iterator iend, + int currentn, + int n, + float iCurveLength, + float step, + float t = 0.0f, + float iCurvilinearLength = 0.0f) + : Interface0DIteratorNested() + { + __A = iA; + __B = iB; + _begin = ibegin; + _end = iend; + _CurvilinearLength = iCurvilinearLength; + _step = step; + _t = t; + _n = n; + _currentn = currentn; + _CurveLength = iCurveLength; + } + + public: + virtual CurvePointIterator *copy() const + { + return new CurvePointIterator(*this); + } + + inline Interface0DIterator castToInterface0DIterator() const + { + Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this)); + return ret; + } + + virtual string getExactTypeName() const + { + return "CurvePointIterator"; + } + + // operators + inline CurvePointIterator &operator++() // operator corresponding to ++i + { + increment(); + return *this; + } + + inline CurvePointIterator &operator--() // operator corresponding to --i + { + decrement(); + return *this; + } + + // comparibility + virtual bool operator==(const Interface0DIteratorNested &b) const + { + const CurvePointIterator *it_exact = dynamic_cast<const CurvePointIterator *>(&b); + if (!it_exact) + return false; + return ((__A == it_exact->__A) && (__B == it_exact->__B) && (_t == it_exact->_t)); + } + + // dereferencing + virtual CurvePoint &operator*() + { + return (_Point = CurvePoint(*__A, *__B, _t)); + } + + virtual CurvePoint *operator->() + { + return &(operator*()); + } + + virtual bool isBegin() const + { + if ((__A == _begin) && (_t < (float)M_EPSILON)) + return true; + return false; + } + + virtual bool isEnd() const + { + if (__B == _end) + return true; + return false; + } + + //protected: + virtual int increment() + { + if ((_currentn == _n - 1) && (_t == 1.0f)) { + // we're setting the iterator to end + ++__A; + ++__B; + ++_currentn; + _t = 0.0f; + return 0; + } + + if (0 == _step) { // means we iterate over initial vertices + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength += (float)vec_tmp.norm(); + if (_currentn == _n - 1) { + _t = 1.0f; + return 0; + } + ++__B; + ++__A; + ++_currentn; + return 0; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = (float)vec_tmp2.norm(); + + if (normAB > M_EPSILON) { + _CurvilinearLength += _step; + _t = _t + _step / normAB; + } + else { + _t = 1.0f; // AB is a null segment, we're directly at its end + } + //if normAB ~= 0, we don't change these values + if (_t >= 1) { + _CurvilinearLength -= normAB * (_t - 1); + if (_currentn == _n - 1) { + _t = 1.0f; + } + else { + _t = 0.0f; + ++_currentn; + ++__A; + ++__B; + } + } + return 0; + } + + virtual int decrement() + { + if (_t == 0.0f) { //we're at the beginning of the edge + _t = 1.0f; + --_currentn; + --__A; + --__B; + if (_currentn == _n - 1) + return 0; + } + + if (0 == _step) { // means we iterate over initial vertices + Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d()); + _CurvilinearLength -= (float)vec_tmp.norm(); + _t = 0; + return 0; + } + + // compute the new position: + Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d()); + float normAB = (float)vec_tmp2.norm(); + + if (normAB > M_EPSILON) { + _CurvilinearLength -= _step; + _t = _t - _step / normAB; + } + else { + _t = -1.0f; // We just need a negative value here + } + + // round value + if (fabs(_t) < (float)M_EPSILON) + _t = 0.0f; + if (_t < 0) { + if (_currentn == 0) + _CurvilinearLength = 0.0f; + else + _CurvilinearLength += normAB * (-_t); + _t = 0.0f; + } + return 0; + } + + virtual float t() const + { + return _CurvilinearLength; + } + + virtual float u() const + { + return _CurvilinearLength / _CurveLength; + } }; -} // end of namespace CurveInternal +} // end of namespace CurveInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_CURVE_ITERATORS_H__ +#endif // __FREESTYLE_CURVE_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h index 95b63362bac..ecdfd25c499 100644 --- a/source/blender/freestyle/intern/stroke/Modifiers.h +++ b/source/blender/freestyle/intern/stroke/Modifiers.h @@ -25,7 +25,7 @@ #include "TimeStamp.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -39,35 +39,37 @@ namespace Freestyle { /*! Base class for modifiers. * Modifiers are used in the Operators in order to "mark" the processed Interface1D. */ -template<class Edge> -struct EdgeModifier : public unary_function<Edge, void> -{ - /*! Default construction */ - EdgeModifier() : unary_function<Edge, void>() {} +template<class Edge> struct EdgeModifier : public unary_function<Edge, void> { + /*! Default construction */ + EdgeModifier() : unary_function<Edge, void>() + { + } - /*! the () operator */ - virtual void operator()(Edge& iEdge) {} + /*! the () operator */ + virtual void operator()(Edge &iEdge) + { + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:EdgeModifier") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:EdgeModifier") #endif }; /*! Modifier that sets the time stamp of an Interface1D to the time stamp of the system. */ -template<class Edge> -struct TimestampModifier : public EdgeModifier<Edge> -{ - /*! Default constructor */ - TimestampModifier() : EdgeModifier<Edge>() {} +template<class Edge> struct TimestampModifier : public EdgeModifier<Edge> { + /*! Default constructor */ + TimestampModifier() : EdgeModifier<Edge>() + { + } - /*! The () operator. */ - virtual void operator()(Edge& iEdge) - { - TimeStamp *timestamp = TimeStamp::instance(); - iEdge.setTimeStamp(timestamp->getTimeStamp()); - } + /*! The () operator. */ + virtual void operator()(Edge &iEdge) + { + TimeStamp *timestamp = TimeStamp::instance(); + iEdge.setTimeStamp(timestamp->getTimeStamp()); + } }; } /* namespace Freestyle */ -#endif // MODIFIERS_H +#endif // MODIFIERS_H diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h index ca0954df561..3e32361eb45 100644 --- a/source/blender/freestyle/intern/stroke/Module.h +++ b/source/blender/freestyle/intern/stroke/Module.h @@ -26,56 +26,55 @@ #include "StyleModule.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class Module -{ -public: - static void setAlwaysRefresh(bool b = true) - { - getCurrentStyleModule()->setAlwaysRefresh(b); - } +class Module { + public: + static void setAlwaysRefresh(bool b = true) + { + getCurrentStyleModule()->setAlwaysRefresh(b); + } - static void setCausal(bool b = true) - { - getCurrentStyleModule()->setCausal(b); - } + static void setCausal(bool b = true) + { + getCurrentStyleModule()->setCausal(b); + } - static void setDrawable(bool b = true) - { - getCurrentStyleModule()->setDrawable(b); - } + static void setDrawable(bool b = true) + { + getCurrentStyleModule()->setDrawable(b); + } - static bool getAlwaysRefresh() - { - return getCurrentStyleModule()->getAlwaysRefresh(); - } + static bool getAlwaysRefresh() + { + return getCurrentStyleModule()->getAlwaysRefresh(); + } - static bool getCausal() - { - return getCurrentStyleModule()->getCausal(); - } + static bool getCausal() + { + return getCurrentStyleModule()->getCausal(); + } - static bool getDrawable() - { - return getCurrentStyleModule()->getDrawable(); - } + static bool getDrawable() + { + return getCurrentStyleModule()->getDrawable(); + } -private: - static StyleModule *getCurrentStyleModule() - { - Canvas *canvas = Canvas::getInstance(); - return canvas->getCurrentStyleModule(); - } + private: + static StyleModule *getCurrentStyleModule() + { + Canvas *canvas = Canvas::getInstance(); + return canvas->getCurrentStyleModule(); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Module") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Module") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_MODULE_H__ +#endif // __FREESTYLE_MODULE_H__ diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp index e9f6ff02f77..2c8a83e2518 100644 --- a/source/blender/freestyle/intern/stroke/Operators.cpp +++ b/source/blender/freestyle/intern/stroke/Operators.cpp @@ -37,1228 +37,1242 @@ Operators::I1DContainer Operators::_current_chains_set; Operators::I1DContainer *Operators::_current_set = NULL; Operators::StrokesContainer Operators::_current_strokes_set; -int Operators::select(UnaryPredicate1D& pred) +int Operators::select(UnaryPredicate1D &pred) { - if (!_current_set) - return 0; - if (_current_set->empty()) - return 0; - I1DContainer new_set; - I1DContainer rejected; - Functions1D::ChainingTimeStampF1D cts; - Functions1D::TimeStampF1D ts; - I1DContainer::iterator it = _current_set->begin(); - I1DContainer::iterator itbegin = it; - while (it != _current_set->end()) { - Interface1D *i1d = *it; - cts(*i1d); // mark everyone's chaining time stamp anyway - if (pred(*i1d) < 0) { - new_set.clear(); - rejected.clear(); - return -1; - } - if (pred.result) { - new_set.push_back(i1d); - ts(*i1d); - } - else { - rejected.push_back(i1d); - } - ++it; - } - if ((*itbegin)->getExactTypeName() != "ViewEdge") { - for (it = rejected.begin(); it != rejected.end(); ++it) - delete *it; - } - rejected.clear(); - _current_set->clear(); - *_current_set = new_set; - return 0; + if (!_current_set) + return 0; + if (_current_set->empty()) + return 0; + I1DContainer new_set; + I1DContainer rejected; + Functions1D::ChainingTimeStampF1D cts; + Functions1D::TimeStampF1D ts; + I1DContainer::iterator it = _current_set->begin(); + I1DContainer::iterator itbegin = it; + while (it != _current_set->end()) { + Interface1D *i1d = *it; + cts(*i1d); // mark everyone's chaining time stamp anyway + if (pred(*i1d) < 0) { + new_set.clear(); + rejected.clear(); + return -1; + } + if (pred.result) { + new_set.push_back(i1d); + ts(*i1d); + } + else { + rejected.push_back(i1d); + } + ++it; + } + if ((*itbegin)->getExactTypeName() != "ViewEdge") { + for (it = rejected.begin(); it != rejected.end(); ++it) + delete *it; + } + rejected.clear(); + _current_set->clear(); + *_current_set = new_set; + return 0; } -int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier) +int Operators::chain(ViewEdgeInternal::ViewEdgeIterator &it, + UnaryPredicate1D &pred, + UnaryFunction1D_void &modifier) { - if (_current_view_edges_set.empty()) - return 0; - - unsigned id = 0; - ViewEdge *edge; - I1DContainer new_chains_set; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred(**it_edge) < 0) - goto error; - if (pred.result) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain *new_chain = new Chain(id); - ++id; - while (true) { - new_chain->push_viewedge_back(*it, it.getOrientation()); - if (modifier(**it) < 0) { - delete new_chain; - goto error; - } - ++it; - if (it.isEnd()) - break; - if (pred(**it) < 0) { - delete new_chain; - goto error; - } - if (pred.result) - break; - } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); - } - new_chains_set.clear(); - _current_set = &_current_chains_set; - } - return 0; + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + ViewEdge *edge; + I1DContainer new_chains_set; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + goto error; + if (pred.result) + continue; + + edge = dynamic_cast<ViewEdge *>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain *new_chain = new Chain(id); + ++id; + while (true) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + if (modifier(**it) < 0) { + delete new_chain; + goto error; + } + ++it; + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + goto error; + } + if (pred.result) + break; + } + new_chains_set.push_back(new_chain); + } + + if (!new_chains_set.empty()) { + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + _current_chains_set.push_back(*it); + } + new_chains_set.clear(); + _current_set = &_current_chains_set; + } + return 0; error: - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - delete (*it); - } - new_chains_set.clear(); - return -1; + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + delete (*it); + } + new_chains_set.clear(); + return -1; } -int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred) +int Operators::chain(ViewEdgeInternal::ViewEdgeIterator &it, UnaryPredicate1D &pred) { - if (_current_view_edges_set.empty()) - return 0; - - unsigned id = 0; - Functions1D::IncrementChainingTimeStampF1D ts; - Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); - ViewEdge *edge; - I1DContainer new_chains_set; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred(**it_edge) < 0) - goto error; - if (pred.result) - continue; - if (pred_ts(**it_edge) < 0) - goto error; - if (pred_ts.result) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain *new_chain = new Chain(id); - ++id; - while (true) { - new_chain->push_viewedge_back(*it, it.getOrientation()); - ts(**it); - ++it; - if (it.isEnd()) - break; - if (pred(**it) < 0) { - delete new_chain; - goto error; - } - if (pred.result) - break; - if (pred_ts(**it) < 0) { - delete new_chain; - goto error; - } - if (pred_ts.result) - break; - } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); - } - new_chains_set.clear(); - _current_set = &_current_chains_set; - } - return 0; + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); + ViewEdge *edge; + I1DContainer new_chains_set; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + goto error; + if (pred.result) + continue; + if (pred_ts(**it_edge) < 0) + goto error; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge *>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain *new_chain = new Chain(id); + ++id; + while (true) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + ++it; + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + goto error; + } + if (pred.result) + break; + if (pred_ts(**it) < 0) { + delete new_chain; + goto error; + } + if (pred_ts.result) + break; + } + new_chains_set.push_back(new_chain); + } + + if (!new_chains_set.empty()) { + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + _current_chains_set.push_back(*it); + } + new_chains_set.clear(); + _current_set = &_current_chains_set; + } + return 0; error: - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - delete (*it); - } - new_chains_set.clear(); - return -1; + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + delete (*it); + } + new_chains_set.clear(); + return -1; } - #if 0 void Operators::bidirectionalChain(ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier) { - if (_current_view_edges_set.empty()) - return; - - unsigned id = 0; - ViewEdge *edge; - Chain *new_chain; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred(**it_edge)) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain *new_chain = new Chain(id); - ++id; -#if 0 // FIXME - ViewEdgeIterator it_back(it); - --it_back; -#endif - do { - new_chain->push_viewedge_back(*it, it.getOrientation()); - modifier(**it); - ++it; - } while (!it.isEnd() && !pred(**it)); - it.setBegin(edge); - it.setCurrentEdge(edge); - --it; - while (!it.isEnd() && !pred(**it)) { - new_chain->push_viewedge_front(*it, it.getOrientation()); - modifier(**it); - --it; - } - - _current_chains_set.push_back(new_chain); - } - - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; + if (_current_view_edges_set.empty()) + return; + + unsigned id = 0; + ViewEdge *edge; + Chain *new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) + { + if (pred(**it_edge)) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain *new_chain = new Chain(id); + ++id; +# if 0 // FIXME + ViewEdgeIterator it_back(it); + --it_back; +# endif + do { + new_chain->push_viewedge_back(*it, it.getOrientation()); + modifier(**it); + ++it; + } while (!it.isEnd() && !pred(**it)); + it.setBegin(edge); + it.setCurrentEdge(edge); + --it; + while (!it.isEnd() && !pred(**it)) { + new_chain->push_viewedge_front(*it, it.getOrientation()); + modifier(**it); + --it; + } + + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; } void Operators::bidirectionalChain(ViewEdgeIterator& it, UnaryPredicate1D& pred) { - if (_current_view_edges_set.empty()) - return; - - unsigned id = 0; - Functions1D::IncrementChainingTimeStampF1D ts; - Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); - - ViewEdge *edge; - Chain *new_chain; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred(**it_edge) || pred_ts(**it_edge)) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain *new_chain = new Chain(id); - ++id; -#if 0 //FIXME - ViewEdgeIterator it_back(it); - --it_back; -#endif - do { - new_chain->push_viewedge_back(*it, it.getOrientation()); - ts(**it); - ++it; - } while (!it.isEnd() && !pred(**it) && !pred_ts(**it)); - it.setBegin(edge); - it.setCurrentEdge(edge); - --it; - while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) { - new_chain->push_viewedge_front(*it, it.getOrientation()); - ts(**it); - --it; - } - - _current_chains_set.push_back(new_chain); - } - - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; + if (_current_view_edges_set.empty()) + return; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); + + ViewEdge *edge; + Chain *new_chain; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) + { + if (pred(**it_edge) || pred_ts(**it_edge)) + continue; + + edge = dynamic_cast<ViewEdge*>(*it_edge); + it.setBegin(edge); + it.setCurrentEdge(edge); + + Chain *new_chain = new Chain(id); + ++id; +# if 0 //FIXME + ViewEdgeIterator it_back(it); + --it_back; +# endif + do { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + ++it; + } while (!it.isEnd() && !pred(**it) && !pred_ts(**it)); + it.setBegin(edge); + it.setCurrentEdge(edge); + --it; + while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) { + new_chain->push_viewedge_front(*it, it.getOrientation()); + ts(**it); + --it; + } + + _current_chains_set.push_back(new_chain); + } + + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; } #endif -int Operators::bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred) +int Operators::bidirectionalChain(ChainingIterator &it, UnaryPredicate1D &pred) { - if (_current_view_edges_set.empty()) - return 0; - - unsigned id = 0; - Functions1D::IncrementChainingTimeStampF1D ts; - Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); - ViewEdge *edge; - I1DContainer new_chains_set; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred(**it_edge) < 0) - goto error; - if (pred.result) - continue; - if (pred_ts(**it_edge) < 0) - goto error; - if (pred_ts.result) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - // re-init iterator - it.setBegin(edge); - it.setCurrentEdge(edge); - it.setOrientation(true); - if (it.init() < 0) - goto error; - - Chain *new_chain = new Chain(id); - ++id; + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); + ViewEdge *edge; + I1DContainer new_chains_set; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred(**it_edge) < 0) + goto error; + if (pred.result) + continue; + if (pred_ts(**it_edge) < 0) + goto error; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge *>(*it_edge); + // re-init iterator + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.init() < 0) + goto error; + + Chain *new_chain = new Chain(id); + ++id; #if 0 // FIXME - ViewEdgeIterator it_back(it); - --it_back; + ViewEdgeIterator it_back(it); + --it_back; #endif - while (true) { - new_chain->push_viewedge_back(*it, it.getOrientation()); - ts(**it); - if (it.increment() < 0) { - delete new_chain; - goto error; - } - if (it.isEnd()) - break; - if (pred(**it) < 0) { - delete new_chain; - goto error; - } - if (pred.result) - break; - } - it.setBegin(edge); - it.setCurrentEdge(edge); - it.setOrientation(true); - if (it.decrement() < 0) { - delete new_chain; - goto error; - } - while (!it.isEnd()) { - if (pred(**it) < 0) { - delete new_chain; - goto error; - } - if (pred.result) - break; - new_chain->push_viewedge_front(*it, it.getOrientation()); - ts(**it); - if (it.decrement() < 0) { - delete new_chain; - goto error; - } - } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); - } - new_chains_set.clear(); - _current_set = &_current_chains_set; - } - return 0; + while (true) { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + if (it.increment() < 0) { + delete new_chain; + goto error; + } + if (it.isEnd()) + break; + if (pred(**it) < 0) { + delete new_chain; + goto error; + } + if (pred.result) + break; + } + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.decrement() < 0) { + delete new_chain; + goto error; + } + while (!it.isEnd()) { + if (pred(**it) < 0) { + delete new_chain; + goto error; + } + if (pred.result) + break; + new_chain->push_viewedge_front(*it, it.getOrientation()); + ts(**it); + if (it.decrement() < 0) { + delete new_chain; + goto error; + } + } + new_chains_set.push_back(new_chain); + } + + if (!new_chains_set.empty()) { + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + _current_chains_set.push_back(*it); + } + new_chains_set.clear(); + _current_set = &_current_chains_set; + } + return 0; error: - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - delete (*it); - } - new_chains_set.clear(); - return -1; + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + delete (*it); + } + new_chains_set.clear(); + return -1; } -int Operators::bidirectionalChain(ChainingIterator& it) +int Operators::bidirectionalChain(ChainingIterator &it) { - if (_current_view_edges_set.empty()) - return 0; - - unsigned id = 0; - Functions1D::IncrementChainingTimeStampF1D ts; - Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); - ViewEdge *edge; - I1DContainer new_chains_set; - - for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); - it_edge != _current_view_edges_set.end(); - ++it_edge) - { - if (pred_ts(**it_edge) < 0) - goto error; - if (pred_ts.result) - continue; - - edge = dynamic_cast<ViewEdge*>(*it_edge); - // re-init iterator - it.setBegin(edge); - it.setCurrentEdge(edge); - it.setOrientation(true); - if (it.init() < 0) - goto error; - - Chain *new_chain = new Chain(id); - ++id; + if (_current_view_edges_set.empty()) + return 0; + + unsigned id = 0; + Functions1D::IncrementChainingTimeStampF1D ts; + Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1); + ViewEdge *edge; + I1DContainer new_chains_set; + + for (I1DContainer::iterator it_edge = _current_view_edges_set.begin(); + it_edge != _current_view_edges_set.end(); + ++it_edge) { + if (pred_ts(**it_edge) < 0) + goto error; + if (pred_ts.result) + continue; + + edge = dynamic_cast<ViewEdge *>(*it_edge); + // re-init iterator + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.init() < 0) + goto error; + + Chain *new_chain = new Chain(id); + ++id; #if 0 // FIXME - ViewEdgeIterator it_back(it); - --it_back; + ViewEdgeIterator it_back(it); + --it_back; #endif - do { - new_chain->push_viewedge_back(*it, it.getOrientation()); - ts(**it); - if (it.increment() < 0) { // FIXME - delete new_chain; - goto error; - } - } while (!it.isEnd()); - it.setBegin(edge); - it.setCurrentEdge(edge); - it.setOrientation(true); - if (it.decrement() < 0) { // FIXME - delete new_chain; - goto error; - } - while (!it.isEnd()) { - new_chain->push_viewedge_front(*it, it.getOrientation()); - ts(**it); - if (it.decrement() < 0) { // FIXME - delete new_chain; - goto error; - } - } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); - } - new_chains_set.clear(); - _current_set = &_current_chains_set; - } - return 0; + do { + new_chain->push_viewedge_back(*it, it.getOrientation()); + ts(**it); + if (it.increment() < 0) { // FIXME + delete new_chain; + goto error; + } + } while (!it.isEnd()); + it.setBegin(edge); + it.setCurrentEdge(edge); + it.setOrientation(true); + if (it.decrement() < 0) { // FIXME + delete new_chain; + goto error; + } + while (!it.isEnd()) { + new_chain->push_viewedge_front(*it, it.getOrientation()); + ts(**it); + if (it.decrement() < 0) { // FIXME + delete new_chain; + goto error; + } + } + new_chains_set.push_back(new_chain); + } + + if (!new_chains_set.empty()) { + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + _current_chains_set.push_back(*it); + } + new_chains_set.clear(); + _current_set = &_current_chains_set; + } + return 0; error: - for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - delete (*it); - } - new_chains_set.clear(); - return -1; + for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { + delete (*it); + } + new_chains_set.clear(); + return -1; } -int Operators::sequentialSplit(UnaryPredicate0D& pred, float sampling) +int Operators::sequentialSplit(UnaryPredicate0D &pred, float sampling) { - if (_current_chains_set.empty()) { - cerr << "Warning: current set empty" << endl; - return 0; - } - CurvePoint *point; - Chain *new_curve; - I1DContainer splitted_chains; - Interface0DIterator first; - Interface0DIterator end; - Interface0DIterator last; - Interface0DIterator it; - I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); - for (; cit != citend; ++cit) { - Id currentId = (*cit)->getId(); - new_curve = new Chain(currentId); - first = (*cit)->pointsBegin(sampling); - end = (*cit)->pointsEnd(sampling); - last = end; - --last; - it = first; - - point = dynamic_cast<CurvePoint*>(&(*it)); - new_curve->push_vertex_back(point); - ++it; - for (; it != end; ++it) { - point = dynamic_cast<CurvePoint*>(&(*it)); - new_curve->push_vertex_back(point); - if (pred(it) < 0) { - delete new_curve; - goto error; - } - if (pred.result && (it != last)) { - splitted_chains.push_back(new_curve); - currentId.setSecond(currentId.getSecond() + 1); - new_curve = new Chain(currentId); - new_curve->push_vertex_back(point); - } - } - if (new_curve->nSegments() == 0) { - delete new_curve; - return 0; - } - - splitted_chains.push_back(new_curve); - } - - // Update the current set of chains: - cit = _current_chains_set.begin(); - for (; cit != citend; ++cit) { - delete (*cit); - } - _current_chains_set.clear(); + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + CurvePoint *point; + Chain *new_curve; + I1DContainer splitted_chains; + Interface0DIterator first; + Interface0DIterator end; + Interface0DIterator last; + Interface0DIterator it; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; cit != citend; ++cit) { + Id currentId = (*cit)->getId(); + new_curve = new Chain(currentId); + first = (*cit)->pointsBegin(sampling); + end = (*cit)->pointsEnd(sampling); + last = end; + --last; + it = first; + + point = dynamic_cast<CurvePoint *>(&(*it)); + new_curve->push_vertex_back(point); + ++it; + for (; it != end; ++it) { + point = dynamic_cast<CurvePoint *>(&(*it)); + new_curve->push_vertex_back(point); + if (pred(it) < 0) { + delete new_curve; + goto error; + } + if (pred.result && (it != last)) { + splitted_chains.push_back(new_curve); + currentId.setSecond(currentId.getSecond() + 1); + new_curve = new Chain(currentId); + new_curve->push_vertex_back(point); + } + } + if (new_curve->nSegments() == 0) { + delete new_curve; + return 0; + } + + splitted_chains.push_back(new_curve); + } + + // Update the current set of chains: + cit = _current_chains_set.begin(); + for (; cit != citend; ++cit) { + delete (*cit); + } + _current_chains_set.clear(); #if 0 - _current_chains_set = splitted_chains; + _current_chains_set = splitted_chains; #else - for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { - if ((*cit)->getLength2D() < M_EPSILON) { - delete (*cit); - continue; - } - _current_chains_set.push_back(*cit); - } + for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); + } #endif - splitted_chains.clear(); + splitted_chains.clear(); - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; - return 0; + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; error: - cit = splitted_chains.begin(); - citend = splitted_chains.end(); - for (; cit != citend; ++cit) { - delete (*cit); - } - splitted_chains.clear(); - return -1; + cit = splitted_chains.begin(); + citend = splitted_chains.end(); + for (; cit != citend; ++cit) { + delete (*cit); + } + splitted_chains.clear(); + return -1; } -int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, float sampling) +int Operators::sequentialSplit(UnaryPredicate0D &startingPred, + UnaryPredicate0D &stoppingPred, + float sampling) { - if (_current_chains_set.empty()) { - cerr << "Warning: current set empty" << endl; - return 0; - } - CurvePoint *point; - Chain *new_curve; - I1DContainer splitted_chains; - Interface0DIterator first; - Interface0DIterator end; - Interface0DIterator last; - Interface0DIterator itStart; - Interface0DIterator itStop; - I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); - for (; cit != citend; ++cit) { - Id currentId = (*cit)->getId(); - first = (*cit)->pointsBegin(sampling); - end = (*cit)->pointsEnd(sampling); - last = end; - --last; - itStart = first; - do { - itStop = itStart; - ++itStop; - - new_curve = new Chain(currentId); - currentId.setSecond(currentId.getSecond() + 1); - - point = dynamic_cast<CurvePoint*>(&(*itStart)); - new_curve->push_vertex_back(point); - do { - point = dynamic_cast<CurvePoint*>(&(*itStop)); - new_curve->push_vertex_back(point); - ++itStop; - if (itStop == end) - break; - if (stoppingPred(itStop) < 0) { - delete new_curve; - goto error; - } - } while (!stoppingPred.result); - if (itStop != end) { - point = dynamic_cast<CurvePoint*>(&(*itStop)); - new_curve->push_vertex_back(point); - } - if (new_curve->nSegments() == 0) { - delete new_curve; - } - else { - splitted_chains.push_back(new_curve); - } - // find next start - do { - ++itStart; - if (itStart == end) - break; - if (startingPred(itStart) < 0) - goto error; - } while (!startingPred.result); - } while ((itStart != end) && (itStart != last)); - } - - // Update the current set of chains: - cit = _current_chains_set.begin(); - for (; cit != citend; ++cit) { - delete (*cit); - } - _current_chains_set.clear(); + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + CurvePoint *point; + Chain *new_curve; + I1DContainer splitted_chains; + Interface0DIterator first; + Interface0DIterator end; + Interface0DIterator last; + Interface0DIterator itStart; + Interface0DIterator itStop; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; cit != citend; ++cit) { + Id currentId = (*cit)->getId(); + first = (*cit)->pointsBegin(sampling); + end = (*cit)->pointsEnd(sampling); + last = end; + --last; + itStart = first; + do { + itStop = itStart; + ++itStop; + + new_curve = new Chain(currentId); + currentId.setSecond(currentId.getSecond() + 1); + + point = dynamic_cast<CurvePoint *>(&(*itStart)); + new_curve->push_vertex_back(point); + do { + point = dynamic_cast<CurvePoint *>(&(*itStop)); + new_curve->push_vertex_back(point); + ++itStop; + if (itStop == end) + break; + if (stoppingPred(itStop) < 0) { + delete new_curve; + goto error; + } + } while (!stoppingPred.result); + if (itStop != end) { + point = dynamic_cast<CurvePoint *>(&(*itStop)); + new_curve->push_vertex_back(point); + } + if (new_curve->nSegments() == 0) { + delete new_curve; + } + else { + splitted_chains.push_back(new_curve); + } + // find next start + do { + ++itStart; + if (itStart == end) + break; + if (startingPred(itStart) < 0) + goto error; + } while (!startingPred.result); + } while ((itStart != end) && (itStart != last)); + } + + // Update the current set of chains: + cit = _current_chains_set.begin(); + for (; cit != citend; ++cit) { + delete (*cit); + } + _current_chains_set.clear(); #if 0 - _current_chains_set = splitted_chains; + _current_chains_set = splitted_chains; #else - for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { - if ((*cit)->getLength2D() < M_EPSILON) { - delete (*cit); - continue; - } - _current_chains_set.push_back(*cit); - } + for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); + } #endif - splitted_chains.clear(); + splitted_chains.clear(); - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; - return 0; + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; error: - cit = splitted_chains.begin(); - citend = splitted_chains.end(); - for (; cit != citend; ++cit) { - delete (*cit); - } - splitted_chains.clear(); - return -1; + cit = splitted_chains.begin(); + citend = splitted_chains.end(); + for (; cit != citend; ++cit) { + delete (*cit); + } + splitted_chains.clear(); + return -1; } // Internal function -static int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling, - Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains) +static int __recursiveSplit(Chain *_curve, + UnaryFunction0D<double> &func, + UnaryPredicate1D &pred, + float sampling, + Operators::I1DContainer &newChains, + Operators::I1DContainer &splitted_chains) { - if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) { - newChains.push_back(_curve); - return 0; - } - - CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); - CurveInternal::CurvePointIterator second = first; - ++second; - CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); - CurveInternal::CurvePointIterator it = second; - CurveInternal::CurvePointIterator split = second; - Interface0DIterator it0d = it.castToInterface0DIterator(); - real _min = FLT_MAX; // func(it0d); - ++it; - CurveInternal::CurvePointIterator next = it; - ++next; - - bool bsplit = false; - for (; ((it != end) && (next != end)); ++it, ++next) { - it0d = it.castToInterface0DIterator(); - if (func(it0d) < 0) - return -1; - if (func.result < _min) { - _min = func.result; - split = it; - bsplit = true; - } - } - - if (!bsplit) { // we didn't find any minimum - newChains.push_back(_curve); - return 0; - } - - // retrieves the current splitting id - Id *newId = _curve->getSplittingId(); - if (newId == 0) { - newId = new Id(_curve->getId()); - _curve->setSplittingId(newId); - } - - Chain *new_curve_a = new Chain(*newId); - newId->setSecond(newId->getSecond() + 1); - new_curve_a->setSplittingId(newId); - Chain *new_curve_b = new Chain(*newId); - newId->setSecond(newId->getSecond() + 1); - new_curve_b->setSplittingId(newId); - - CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend = _curve->curveVerticesEnd(); - CurveInternal::CurvePointIterator vnext = vit; - ++vnext; - - for (; (vit != vitend) && (vnext != vitend) && (vnext._CurvilinearLength < split._CurvilinearLength); - ++vit, ++vnext) - { - new_curve_a->push_vertex_back(&(*vit)); - } - if ((vit == vitend) || (vnext == vitend)) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "The split takes place in bad location" << endl; - } - newChains.push_back(_curve); - delete new_curve_a; - delete new_curve_b; - return 0; - } - - // build the two resulting chains - new_curve_a->push_vertex_back(&(*vit)); - new_curve_a->push_vertex_back(&(*split)); - new_curve_b->push_vertex_back(&(*split)); - - for (vit = vnext; vit != vitend; ++vit) - new_curve_b->push_vertex_back(&(*vit)); - - // let's check whether one or two of the two new curves satisfy the stopping condition or not. - // (if one of them satisfies it, we don't split) - if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { - delete new_curve_a; - delete new_curve_b; - return -1; - } - if (pred.result) { - // we don't actually create these two chains - newChains.push_back(_curve); - delete new_curve_a; - delete new_curve_b; - return 0; - } - // here we know we'll split _curve: - splitted_chains.push_back(_curve); - - __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains); - __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains); - return 0; + if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) { + newChains.push_back(_curve); + return 0; + } + + CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); + CurveInternal::CurvePointIterator second = first; + ++second; + CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); + CurveInternal::CurvePointIterator it = second; + CurveInternal::CurvePointIterator split = second; + Interface0DIterator it0d = it.castToInterface0DIterator(); + real _min = FLT_MAX; // func(it0d); + ++it; + CurveInternal::CurvePointIterator next = it; + ++next; + + bool bsplit = false; + for (; ((it != end) && (next != end)); ++it, ++next) { + it0d = it.castToInterface0DIterator(); + if (func(it0d) < 0) + return -1; + if (func.result < _min) { + _min = func.result; + split = it; + bsplit = true; + } + } + + if (!bsplit) { // we didn't find any minimum + newChains.push_back(_curve); + return 0; + } + + // retrieves the current splitting id + Id *newId = _curve->getSplittingId(); + if (newId == 0) { + newId = new Id(_curve->getId()); + _curve->setSplittingId(newId); + } + + Chain *new_curve_a = new Chain(*newId); + newId->setSecond(newId->getSecond() + 1); + new_curve_a->setSplittingId(newId); + Chain *new_curve_b = new Chain(*newId); + newId->setSecond(newId->getSecond() + 1); + new_curve_b->setSplittingId(newId); + + CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), + vitend = _curve->curveVerticesEnd(); + CurveInternal::CurvePointIterator vnext = vit; + ++vnext; + + for (; (vit != vitend) && (vnext != vitend) && + (vnext._CurvilinearLength < split._CurvilinearLength); + ++vit, ++vnext) { + new_curve_a->push_vertex_back(&(*vit)); + } + if ((vit == vitend) || (vnext == vitend)) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "The split takes place in bad location" << endl; + } + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + + // build the two resulting chains + new_curve_a->push_vertex_back(&(*vit)); + new_curve_a->push_vertex_back(&(*split)); + new_curve_b->push_vertex_back(&(*split)); + + for (vit = vnext; vit != vitend; ++vit) + new_curve_b->push_vertex_back(&(*vit)); + + // let's check whether one or two of the two new curves satisfy the stopping condition or not. + // (if one of them satisfies it, we don't split) + if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { + delete new_curve_a; + delete new_curve_b; + return -1; + } + if (pred.result) { + // we don't actually create these two chains + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + // here we know we'll split _curve: + splitted_chains.push_back(_curve); + + __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains); + __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains); + return 0; } -int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling) +int Operators::recursiveSplit(UnaryFunction0D<double> &func, + UnaryPredicate1D &pred, + float sampling) { - if (_current_chains_set.empty()) { - cerr << "Warning: current set empty" << endl; - return 0; - } - - Chain *currentChain = 0; - I1DContainer splitted_chains; - I1DContainer newChains; - I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); - for (; cit != citend; ++cit) { - currentChain = dynamic_cast<Chain*>(*cit); - if (!currentChain) - continue; - // let's check the first one: - if (pred(*currentChain) < 0) - return -1; - if (!pred.result) { - __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains); - } - else { - newChains.push_back(currentChain); - } - } - // Update the current set of chains: - if (!splitted_chains.empty()) { - for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { - delete (*cit); - } - splitted_chains.clear(); - } - - _current_chains_set.clear(); + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + + Chain *currentChain = 0; + I1DContainer splitted_chains; + I1DContainer newChains; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; cit != citend; ++cit) { + currentChain = dynamic_cast<Chain *>(*cit); + if (!currentChain) + continue; + // let's check the first one: + if (pred(*currentChain) < 0) + return -1; + if (!pred.result) { + __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains); + } + else { + newChains.push_back(currentChain); + } + } + // Update the current set of chains: + if (!splitted_chains.empty()) { + for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { + delete (*cit); + } + splitted_chains.clear(); + } + + _current_chains_set.clear(); #if 0 - _current_chains_set = newChains; + _current_chains_set = newChains; #else - for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { - if ((*cit)->getLength2D() < M_EPSILON) { - delete (*cit); - continue; - } - _current_chains_set.push_back(*cit); - } + for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); + } #endif - newChains.clear(); + newChains.clear(); - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; - return 0; + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; } // recursive split with pred 0D -static int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, - UnaryPredicate1D& pred, float sampling, - Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains) +static int __recursiveSplit(Chain *_curve, + UnaryFunction0D<double> &func, + UnaryPredicate0D &pred0d, + UnaryPredicate1D &pred, + float sampling, + Operators::I1DContainer &newChains, + Operators::I1DContainer &splitted_chains) { - if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) { - newChains.push_back(_curve); - return 0; - } - - CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); - CurveInternal::CurvePointIterator second = first; - ++second; - CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); - CurveInternal::CurvePointIterator it = second; - CurveInternal::CurvePointIterator split = second; - Interface0DIterator it0d = it.castToInterface0DIterator(); + if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) { + newChains.push_back(_curve); + return 0; + } + + CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling); + CurveInternal::CurvePointIterator second = first; + ++second; + CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling); + CurveInternal::CurvePointIterator it = second; + CurveInternal::CurvePointIterator split = second; + Interface0DIterator it0d = it.castToInterface0DIterator(); #if 0 - real _min = func(it0d); - ++it; + real _min = func(it0d); + ++it; #endif - real _min = FLT_MAX; - ++it; - real mean = 0.f; - //soc unused - real variance = 0.0f; - unsigned count = 0; - CurveInternal::CurvePointIterator next = it; - ++next; - - bool bsplit = false; - for (; ((it != end) && (next != end)); ++it, ++next) { - ++count; - it0d = it.castToInterface0DIterator(); - if (pred0d(it0d) < 0) - return -1; - if (!pred0d.result) - continue; - if (func(it0d) < 0) - return -1; - mean += func.result; - if (func.result < _min) { - _min = func.result; - split = it; - bsplit = true; - } - } - mean /= (float)count; - - //if ((!bsplit) || (mean - _min > mean)) { // we didn't find any minimum - if (!bsplit) { // we didn't find any minimum - newChains.push_back(_curve); - return 0; - } - - // retrieves the current splitting id - Id *newId = _curve->getSplittingId(); - if (newId == NULL) { - newId = new Id(_curve->getId()); - _curve->setSplittingId(newId); - } - - Chain *new_curve_a = new Chain(*newId); - newId->setSecond(newId->getSecond() + 1); - new_curve_a->setSplittingId(newId); - Chain *new_curve_b = new Chain(*newId); - newId->setSecond(newId->getSecond() + 1); - new_curve_b->setSplittingId(newId); - - CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend = _curve->curveVerticesEnd(); - CurveInternal::CurvePointIterator vnext = vit; - ++vnext; - - for (; - (vit != vitend) && (vnext != vitend) && (vnext._CurvilinearLength < split._CurvilinearLength); - ++vit, ++vnext) - { - new_curve_a->push_vertex_back(&(*vit)); - } - if ((vit == vitend) || (vnext == vitend)) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "The split takes place in bad location" << endl; - } - newChains.push_back(_curve); - delete new_curve_a; - delete new_curve_b; - return 0; - } - - // build the two resulting chains - new_curve_a->push_vertex_back(&(*vit)); - new_curve_a->push_vertex_back(&(*split)); - new_curve_b->push_vertex_back(&(*split)); - - for (vit = vnext; vit != vitend; ++vit) - new_curve_b->push_vertex_back(&(*vit)); - - // let's check whether one or two of the two new curves satisfy the stopping condition or not. - // (if one of them satisfies it, we don't split) - if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { - delete new_curve_a; - delete new_curve_b; - return -1; - } - if (pred.result) { - // we don't actually create these two chains - newChains.push_back(_curve); - delete new_curve_a; - delete new_curve_b; - return 0; - } - // here we know we'll split _curve: - splitted_chains.push_back(_curve); - - __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains); - __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains); - return 0; + real _min = FLT_MAX; + ++it; + real mean = 0.f; + //soc unused - real variance = 0.0f; + unsigned count = 0; + CurveInternal::CurvePointIterator next = it; + ++next; + + bool bsplit = false; + for (; ((it != end) && (next != end)); ++it, ++next) { + ++count; + it0d = it.castToInterface0DIterator(); + if (pred0d(it0d) < 0) + return -1; + if (!pred0d.result) + continue; + if (func(it0d) < 0) + return -1; + mean += func.result; + if (func.result < _min) { + _min = func.result; + split = it; + bsplit = true; + } + } + mean /= (float)count; + + //if ((!bsplit) || (mean - _min > mean)) { // we didn't find any minimum + if (!bsplit) { // we didn't find any minimum + newChains.push_back(_curve); + return 0; + } + + // retrieves the current splitting id + Id *newId = _curve->getSplittingId(); + if (newId == NULL) { + newId = new Id(_curve->getId()); + _curve->setSplittingId(newId); + } + + Chain *new_curve_a = new Chain(*newId); + newId->setSecond(newId->getSecond() + 1); + new_curve_a->setSplittingId(newId); + Chain *new_curve_b = new Chain(*newId); + newId->setSecond(newId->getSecond() + 1); + new_curve_b->setSplittingId(newId); + + CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), + vitend = _curve->curveVerticesEnd(); + CurveInternal::CurvePointIterator vnext = vit; + ++vnext; + + for (; (vit != vitend) && (vnext != vitend) && + (vnext._CurvilinearLength < split._CurvilinearLength); + ++vit, ++vnext) { + new_curve_a->push_vertex_back(&(*vit)); + } + if ((vit == vitend) || (vnext == vitend)) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "The split takes place in bad location" << endl; + } + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + + // build the two resulting chains + new_curve_a->push_vertex_back(&(*vit)); + new_curve_a->push_vertex_back(&(*split)); + new_curve_b->push_vertex_back(&(*split)); + + for (vit = vnext; vit != vitend; ++vit) + new_curve_b->push_vertex_back(&(*vit)); + + // let's check whether one or two of the two new curves satisfy the stopping condition or not. + // (if one of them satisfies it, we don't split) + if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) { + delete new_curve_a; + delete new_curve_b; + return -1; + } + if (pred.result) { + // we don't actually create these two chains + newChains.push_back(_curve); + delete new_curve_a; + delete new_curve_b; + return 0; + } + // here we know we'll split _curve: + splitted_chains.push_back(_curve); + + __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains); + __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains); + return 0; } -int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, +int Operators::recursiveSplit(UnaryFunction0D<double> &func, + UnaryPredicate0D &pred0d, + UnaryPredicate1D &pred, float sampling) { - if (_current_chains_set.empty()) { - cerr << "Warning: current set empty" << endl; - return 0; - } - - Chain *currentChain = 0; - I1DContainer splitted_chains; - I1DContainer newChains; - I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); - for (; cit != citend; ++cit) { - currentChain = dynamic_cast<Chain*>(*cit); - if (!currentChain) - continue; - // let's check the first one: - if (pred(*currentChain) < 0) - return -1; - if (!pred.result) { - __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains); - } - else { - newChains.push_back(currentChain); - } - } - // Update the current set of chains: - if (!splitted_chains.empty()) { - for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { - delete (*cit); - } - splitted_chains.clear(); - } - - _current_chains_set.clear(); + if (_current_chains_set.empty()) { + cerr << "Warning: current set empty" << endl; + return 0; + } + + Chain *currentChain = 0; + I1DContainer splitted_chains; + I1DContainer newChains; + I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end(); + for (; cit != citend; ++cit) { + currentChain = dynamic_cast<Chain *>(*cit); + if (!currentChain) + continue; + // let's check the first one: + if (pred(*currentChain) < 0) + return -1; + if (!pred.result) { + __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains); + } + else { + newChains.push_back(currentChain); + } + } + // Update the current set of chains: + if (!splitted_chains.empty()) { + for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) { + delete (*cit); + } + splitted_chains.clear(); + } + + _current_chains_set.clear(); #if 0 - _current_chains_set = newChains; + _current_chains_set = newChains; #else - for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { - if ((*cit)->getLength2D() < M_EPSILON) { - delete (*cit); - continue; - } - _current_chains_set.push_back(*cit); - } + for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); + } #endif - newChains.clear(); + newChains.clear(); - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; - return 0; + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; + return 0; } // Internal class -class PredicateWrapper -{ -public: - inline PredicateWrapper(BinaryPredicate1D& pred) - { - _pred = &pred; - } - - inline bool operator()(Interface1D *i1, Interface1D *i2) - { - if (i1 == i2) - return false; - if ((*_pred)(*i1, *i2) < 0) - throw std::runtime_error("comparison failed"); - return _pred->result; - } - -private: - BinaryPredicate1D *_pred; +class PredicateWrapper { + public: + inline PredicateWrapper(BinaryPredicate1D &pred) + { + _pred = &pred; + } + + inline bool operator()(Interface1D *i1, Interface1D *i2) + { + if (i1 == i2) + return false; + if ((*_pred)(*i1, *i2) < 0) + throw std::runtime_error("comparison failed"); + return _pred->result; + } + + private: + BinaryPredicate1D *_pred; }; -int Operators::sort(BinaryPredicate1D& pred) +int Operators::sort(BinaryPredicate1D &pred) { - if (!_current_set) - return 0; - PredicateWrapper wrapper(pred); - try { - std::sort(_current_set->begin(), _current_set->end(), wrapper); - } - catch (std::runtime_error &e) { - cerr << "Warning: Operator.sort(): " << e.what() << endl; - return -1; - } - return 0; + if (!_current_set) + return 0; + PredicateWrapper wrapper(pred); + try { + std::sort(_current_set->begin(), _current_set->end(), wrapper); + } + catch (std::runtime_error &e) { + cerr << "Warning: Operator.sort(): " << e.what() << endl; + return -1; + } + return 0; } -static Stroke *createStroke(Interface1D& inter) +static Stroke *createStroke(Interface1D &inter) { - Stroke *stroke = new Stroke; - stroke->setId(inter.getId()); - - float currentCurvilignAbscissa = 0.0f; - - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - Interface0DIterator itfirst = it; - - Vec2r current(it->getPoint2D()); - Vec2r previous = current; - SVertex *sv; - CurvePoint *cp; - StrokeVertex *stroke_vertex = NULL; - bool hasSingularity = false; - - do { - cp = dynamic_cast<CurvePoint*>(&(*it)); - if (!cp) { - sv = dynamic_cast<SVertex*>(&(*it)); - if (!sv) { - cerr << "Warning: unexpected Vertex type" << endl; - continue; - } - stroke_vertex = new StrokeVertex(sv); - } - else { - stroke_vertex = new StrokeVertex(cp); - } - current = stroke_vertex->getPoint2D(); - Vec2r vec_tmp(current - previous); - real dist = vec_tmp.norm(); - if (dist < 1.0e-6) - hasSingularity = true; - currentCurvilignAbscissa += dist; - stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); - stroke->push_back(stroke_vertex); - previous = current; - ++it; - } while ((it != itend) && (it != itfirst)); - - if (it == itfirst) { - // Add last vertex: - cp = dynamic_cast<CurvePoint*>(&(*it)); - if (!cp) { - sv = dynamic_cast<SVertex*>(&(*it)); - if (!sv) - cerr << "Warning: unexpected Vertex type" << endl; - else - stroke_vertex = new StrokeVertex(sv); - } - else { - stroke_vertex = new StrokeVertex(cp); - } - current = stroke_vertex->getPoint2D(); - Vec2r vec_tmp(current - previous); - real dist = vec_tmp.norm(); - if (dist < 1.0e-6) - hasSingularity = true; - currentCurvilignAbscissa += dist; - stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); - stroke->push_back(stroke_vertex); - } - // Discard the stroke if the number of stroke vertices is less than two - if (stroke->strokeVerticesSize() < 2) { - delete stroke; - return NULL; - } - stroke->setLength(currentCurvilignAbscissa); - if (hasSingularity) { - // Try to address singular points such that the distance between two subsequent vertices - // are smaller than epsilon. - StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator vnext = v; - ++vnext; - Vec2r next((*v).getPoint()); - while (!vnext.isEnd()) { - current = next; - next = (*vnext).getPoint(); - if ((next - current).norm() < 1.0e-6) { - StrokeInternal::StrokeVertexIterator vprevious = v; - if (!vprevious.isBegin()) - --vprevious; - - // collect a set of overlapping vertices - std::vector<StrokeVertex *> overlapping_vertices; - overlapping_vertices.push_back(&(*v)); - do { - overlapping_vertices.push_back(&(*vnext)); - current = next; - ++v; - ++vnext; - if (vnext.isEnd()) - break; - next = (*vnext).getPoint(); - } while ((next - current).norm() < 1.0e-6); - - Vec2r target; - bool reverse; - if (!vnext.isEnd()) { - target = (*vnext).getPoint(); - reverse = false; - } - else if (!vprevious.isBegin()) { - target = (*vprevious).getPoint(); - reverse = true; - } - else { - // Discard the stroke because all stroke vertices are overlapping - delete stroke; - return NULL; - } - current = overlapping_vertices.front()->getPoint(); - Vec2r dir(target - current); - real dist = dir.norm(); - real len = 1.0e-3; // default offset length - int nvert = overlapping_vertices.size(); - if (dist < len * nvert) { - len = dist / nvert; - } - dir.normalize(); - Vec2r offset(dir * len); - // add the offset to the overlapping vertices - StrokeVertex *sv; - std::vector<StrokeVertex *>::iterator it = overlapping_vertices.begin(); - if (!reverse) { - for (int n = 0; n < nvert; n++) { - sv = (*it); - sv->setPoint(sv->getPoint() + offset * (n + 1)); - ++it; - } - } - else { - for (int n = 0; n < nvert; n++) { - sv = (*it); - sv->setPoint(sv->getPoint() + offset * (nvert - n)); - ++it; - } - } - - if (vnext.isEnd()) - break; - } - ++v; - ++vnext; - } - } - { - // Check if the stroke no longer contains singular points - Interface0DIterator v = stroke->verticesBegin(); - Interface0DIterator vnext = v; - ++vnext; - Vec2r next((*v).getPoint2D()); - bool warning = false; - while (!vnext.isEnd()) { - current = next; - next = (*vnext).getPoint2D(); - if ((next - current).norm() < 1.0e-6) { - warning = true; - break; - } - ++v; - ++vnext; - } - if (warning && G.debug & G_DEBUG_FREESTYLE) { - printf("Warning: stroke contains singular points.\n"); - } - } - return stroke; + Stroke *stroke = new Stroke; + stroke->setId(inter.getId()); + + float currentCurvilignAbscissa = 0.0f; + + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + Interface0DIterator itfirst = it; + + Vec2r current(it->getPoint2D()); + Vec2r previous = current; + SVertex *sv; + CurvePoint *cp; + StrokeVertex *stroke_vertex = NULL; + bool hasSingularity = false; + + do { + cp = dynamic_cast<CurvePoint *>(&(*it)); + if (!cp) { + sv = dynamic_cast<SVertex *>(&(*it)); + if (!sv) { + cerr << "Warning: unexpected Vertex type" << endl; + continue; + } + stroke_vertex = new StrokeVertex(sv); + } + else { + stroke_vertex = new StrokeVertex(cp); + } + current = stroke_vertex->getPoint2D(); + Vec2r vec_tmp(current - previous); + real dist = vec_tmp.norm(); + if (dist < 1.0e-6) + hasSingularity = true; + currentCurvilignAbscissa += dist; + stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); + stroke->push_back(stroke_vertex); + previous = current; + ++it; + } while ((it != itend) && (it != itfirst)); + + if (it == itfirst) { + // Add last vertex: + cp = dynamic_cast<CurvePoint *>(&(*it)); + if (!cp) { + sv = dynamic_cast<SVertex *>(&(*it)); + if (!sv) + cerr << "Warning: unexpected Vertex type" << endl; + else + stroke_vertex = new StrokeVertex(sv); + } + else { + stroke_vertex = new StrokeVertex(cp); + } + current = stroke_vertex->getPoint2D(); + Vec2r vec_tmp(current - previous); + real dist = vec_tmp.norm(); + if (dist < 1.0e-6) + hasSingularity = true; + currentCurvilignAbscissa += dist; + stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa); + stroke->push_back(stroke_vertex); + } + // Discard the stroke if the number of stroke vertices is less than two + if (stroke->strokeVerticesSize() < 2) { + delete stroke; + return NULL; + } + stroke->setLength(currentCurvilignAbscissa); + if (hasSingularity) { + // Try to address singular points such that the distance between two subsequent vertices + // are smaller than epsilon. + StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator vnext = v; + ++vnext; + Vec2r next((*v).getPoint()); + while (!vnext.isEnd()) { + current = next; + next = (*vnext).getPoint(); + if ((next - current).norm() < 1.0e-6) { + StrokeInternal::StrokeVertexIterator vprevious = v; + if (!vprevious.isBegin()) + --vprevious; + + // collect a set of overlapping vertices + std::vector<StrokeVertex *> overlapping_vertices; + overlapping_vertices.push_back(&(*v)); + do { + overlapping_vertices.push_back(&(*vnext)); + current = next; + ++v; + ++vnext; + if (vnext.isEnd()) + break; + next = (*vnext).getPoint(); + } while ((next - current).norm() < 1.0e-6); + + Vec2r target; + bool reverse; + if (!vnext.isEnd()) { + target = (*vnext).getPoint(); + reverse = false; + } + else if (!vprevious.isBegin()) { + target = (*vprevious).getPoint(); + reverse = true; + } + else { + // Discard the stroke because all stroke vertices are overlapping + delete stroke; + return NULL; + } + current = overlapping_vertices.front()->getPoint(); + Vec2r dir(target - current); + real dist = dir.norm(); + real len = 1.0e-3; // default offset length + int nvert = overlapping_vertices.size(); + if (dist < len * nvert) { + len = dist / nvert; + } + dir.normalize(); + Vec2r offset(dir * len); + // add the offset to the overlapping vertices + StrokeVertex *sv; + std::vector<StrokeVertex *>::iterator it = overlapping_vertices.begin(); + if (!reverse) { + for (int n = 0; n < nvert; n++) { + sv = (*it); + sv->setPoint(sv->getPoint() + offset * (n + 1)); + ++it; + } + } + else { + for (int n = 0; n < nvert; n++) { + sv = (*it); + sv->setPoint(sv->getPoint() + offset * (nvert - n)); + ++it; + } + } + + if (vnext.isEnd()) + break; + } + ++v; + ++vnext; + } + } + { + // Check if the stroke no longer contains singular points + Interface0DIterator v = stroke->verticesBegin(); + Interface0DIterator vnext = v; + ++vnext; + Vec2r next((*v).getPoint2D()); + bool warning = false; + while (!vnext.isEnd()) { + current = next; + next = (*vnext).getPoint2D(); + if ((next - current).norm() < 1.0e-6) { + warning = true; + break; + } + ++v; + ++vnext; + } + if (warning && G.debug & G_DEBUG_FREESTYLE) { + printf("Warning: stroke contains singular points.\n"); + } + } + return stroke; } - -inline int applyShading(Stroke& stroke, vector<StrokeShader*>& shaders) +inline int applyShading(Stroke &stroke, vector<StrokeShader *> &shaders) { - for (vector<StrokeShader*>::iterator it = shaders.begin(); it != shaders.end(); ++it) { - if ((*it)->shade(stroke) < 0) { - return -1; - } - } - return 0; + for (vector<StrokeShader *>::iterator it = shaders.begin(); it != shaders.end(); ++it) { + if ((*it)->shade(stroke) < 0) { + return -1; + } + } + return 0; } -int Operators::create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders) +int Operators::create(UnaryPredicate1D &pred, vector<StrokeShader *> shaders) { - //Canvas* canvas = Canvas::getInstance(); - if (!_current_set) { - cerr << "Warning: current set empty" << endl; - return 0; - } - StrokesContainer new_strokes_set; - for (Operators::I1DContainer::iterator it = _current_set->begin(); it != _current_set->end(); ++it) { - if (pred(**it) < 0) - goto error; - if (!pred.result) - continue; - - Stroke *stroke = createStroke(**it); - if (stroke) { - if (applyShading(*stroke, shaders) < 0) { - delete stroke; - goto error; - } - //canvas->RenderStroke(stroke); - new_strokes_set.push_back(stroke); - } - } - - for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) { - _current_strokes_set.push_back(*it); - } - new_strokes_set.clear(); - return 0; + //Canvas* canvas = Canvas::getInstance(); + if (!_current_set) { + cerr << "Warning: current set empty" << endl; + return 0; + } + StrokesContainer new_strokes_set; + for (Operators::I1DContainer::iterator it = _current_set->begin(); it != _current_set->end(); + ++it) { + if (pred(**it) < 0) + goto error; + if (!pred.result) + continue; + + Stroke *stroke = createStroke(**it); + if (stroke) { + if (applyShading(*stroke, shaders) < 0) { + delete stroke; + goto error; + } + //canvas->RenderStroke(stroke); + new_strokes_set.push_back(stroke); + } + } + + for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); + ++it) { + _current_strokes_set.push_back(*it); + } + new_strokes_set.clear(); + return 0; error: - for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) { - delete (*it); - } - new_strokes_set.clear(); - return -1; + for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); + ++it) { + delete (*it); + } + new_strokes_set.clear(); + return -1; } void Operators::reset(bool removeStrokes) { - ViewMap *vm = ViewMap::getInstance(); - if (!vm) { - cerr << "Error: no ViewMap computed yet" << endl; - return; - } - _current_view_edges_set.clear(); - for (I1DContainer::iterator it = _current_chains_set.begin(); it != _current_chains_set.end(); ++it) - delete *it; - _current_chains_set.clear(); - - ViewMap::viewedges_container& vedges = vm->ViewEdges(); - ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end(); - for (; ve != veend; ++ve) { - if ((*ve)->getLength2D() < M_EPSILON) - continue; - _current_view_edges_set.push_back(*ve); - } - _current_set = &_current_view_edges_set; - if (removeStrokes) - _current_strokes_set.clear(); + ViewMap *vm = ViewMap::getInstance(); + if (!vm) { + cerr << "Error: no ViewMap computed yet" << endl; + return; + } + _current_view_edges_set.clear(); + for (I1DContainer::iterator it = _current_chains_set.begin(); it != _current_chains_set.end(); + ++it) + delete *it; + _current_chains_set.clear(); + + ViewMap::viewedges_container &vedges = vm->ViewEdges(); + ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end(); + for (; ve != veend; ++ve) { + if ((*ve)->getLength2D() < M_EPSILON) + continue; + _current_view_edges_set.push_back(*ve); + } + _current_set = &_current_view_edges_set; + if (removeStrokes) + _current_strokes_set.clear(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h index 6c3d9413038..9d63108a813 100644 --- a/source/blender/freestyle/intern/stroke/Operators.h +++ b/source/blender/freestyle/intern/stroke/Operators.h @@ -37,7 +37,7 @@ #include "../view_map/ViewMap.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -48,225 +48,235 @@ namespace Freestyle { */ class 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(bool removeStrokes=true); - -private: - Operators() {} - - static I1DContainer _current_view_edges_set; - static I1DContainer _current_chains_set; - static I1DContainer *_current_set; - static StrokesContainer _current_strokes_set; + 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(bool removeStrokes = true); + + private: + Operators() + { + } + + static I1DContainer _current_view_edges_set; + static I1DContainer _current_chains_set; + static I1DContainer *_current_set; + static StrokesContainer _current_strokes_set; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Operators") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Operators") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_OPERATORS_H__ +#endif // __FREESTYLE_OPERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp index 3cdf7904998..20dac647cdc 100644 --- a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp @@ -26,72 +26,73 @@ namespace Freestyle { PSStrokeRenderer::PSStrokeRenderer(const char *iFileName) : StrokeRenderer() { - if (!iFileName) - iFileName = "freestyle.ps"; - // open the stream: - _ofstream.open(iFileName, ios::out); - if (!_ofstream.is_open()) { - cerr << "couldn't open the output file " << iFileName << endl; - } - _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl; - _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; - _ofstream << "%%BoundingBox: " << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << - Canvas::getInstance()->height() << endl; - _ofstream << "%%EndComments" << endl; + if (!iFileName) + iFileName = "freestyle.ps"; + // open the stream: + _ofstream.open(iFileName, ios::out); + if (!_ofstream.is_open()) { + cerr << "couldn't open the output file " << iFileName << endl; + } + _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl; + _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; + _ofstream << "%%BoundingBox: " << 0 << " " << 0 << " " << Canvas::getInstance()->width() << " " + << Canvas::getInstance()->height() << endl; + _ofstream << "%%EndComments" << endl; } PSStrokeRenderer::~PSStrokeRenderer() { - Close(); + Close(); } void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const { - RenderStrokeRepBasic(iStrokeRep); + RenderStrokeRepBasic(iStrokeRep); } void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const { - vector<Strip*>& strips = iStrokeRep->getStrips(); - Strip::vertex_container::iterator v[3]; - StrokeVertexRep *svRep[3]; - Vec3r color[3]; - for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) { - Strip::vertex_container& vertices = (*s)->vertices(); - v[0] = vertices.begin(); - v[1] = v[0]; - ++(v[1]); - v[2] = v[1]; - ++(v[2]); + vector<Strip *> &strips = iStrokeRep->getStrips(); + Strip::vertex_container::iterator v[3]; + StrokeVertexRep *svRep[3]; + Vec3r color[3]; + for (vector<Strip *>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) { + Strip::vertex_container &vertices = (*s)->vertices(); + v[0] = vertices.begin(); + v[1] = v[0]; + ++(v[1]); + v[2] = v[1]; + ++(v[2]); - while (v[2] != vertices.end()) { - svRep[0] = *(v[0]); - svRep[1] = *(v[1]); - svRep[2] = *(v[2]); + while (v[2] != vertices.end()) { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); - color[0] = svRep[0]->color(); - //color[1] = svRep[1]->color(); - //color[2] = svRep[2]->color(); + color[0] = svRep[0]->color(); + //color[1] = svRep[1]->color(); + //color[2] = svRep[2]->color(); - _ofstream << "newpath" << endl; - _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" <<endl; - _ofstream << svRep[0]->point2d()[0] << " " <<svRep[0]->point2d()[1] << " moveto" << endl; - _ofstream << svRep[1]->point2d()[0] << " " <<svRep[1]->point2d()[1] << " lineto" << endl; - _ofstream << svRep[2]->point2d()[0] << " " <<svRep[2]->point2d()[1] << " lineto" << endl; - _ofstream << "closepath" << endl; - _ofstream << "fill" << endl; + _ofstream << "newpath" << endl; + _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" + << endl; + _ofstream << svRep[0]->point2d()[0] << " " << svRep[0]->point2d()[1] << " moveto" << endl; + _ofstream << svRep[1]->point2d()[0] << " " << svRep[1]->point2d()[1] << " lineto" << endl; + _ofstream << svRep[2]->point2d()[0] << " " << svRep[2]->point2d()[1] << " lineto" << endl; + _ofstream << "closepath" << endl; + _ofstream << "fill" << endl; - ++v[0]; - ++v[1]; - ++v[2]; - } - } + ++v[0]; + ++v[1]; + ++v[2]; + } + } } void PSStrokeRenderer::Close() { - if (_ofstream.is_open()) - _ofstream.close(); + if (_ofstream.is_open()) + _ofstream.close(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h index e24188be2f9..7ddd3d3e4c0 100644 --- a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h @@ -38,23 +38,22 @@ namespace Freestyle { /* */ /**********************************/ -class PSStrokeRenderer : public StrokeRenderer -{ -public: - PSStrokeRenderer(const char *iFileName = NULL); - virtual ~PSStrokeRenderer(); +class PSStrokeRenderer : public StrokeRenderer { + public: + PSStrokeRenderer(const char *iFileName = NULL); + virtual ~PSStrokeRenderer(); - /*! Renders a stroke rep */ - virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; - virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; - /*! Closes the output PS file */ - void Close(); + /*! Closes the output PS file */ + void Close(); -protected: - mutable ofstream _ofstream; + protected: + mutable ofstream _ofstream; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_PS_STROKE_RENDERER_H__ +#endif // __FREESTYLE_PS_STROKE_RENDERER_H__ diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.cpp b/source/blender/freestyle/intern/stroke/Predicates0D.cpp index e0263abd387..e28a847df26 100644 --- a/source/blender/freestyle/intern/stroke/Predicates0D.cpp +++ b/source/blender/freestyle/intern/stroke/Predicates0D.cpp @@ -24,14 +24,14 @@ namespace Freestyle { -int UnaryPredicate0D::operator()(Interface0DIterator& it) +int UnaryPredicate0D::operator()(Interface0DIterator &it) { - return Director_BPy_UnaryPredicate0D___call__(this, it); + return Director_BPy_UnaryPredicate0D___call__(this, it); } -int BinaryPredicate0D::operator()(Interface0D& inter1, Interface0D& inter2) +int BinaryPredicate0D::operator()(Interface0D &inter1, Interface0D &inter2) { - return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2); + return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h index 4309c942218..f511c0ceade 100644 --- a/source/blender/freestyle/intern/stroke/Predicates0D.h +++ b/source/blender/freestyle/intern/stroke/Predicates0D.h @@ -25,7 +25,7 @@ #include "../view_map/Functions0D.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -41,40 +41,40 @@ namespace Freestyle { * The UnaryPredicate0D is used by calling its () operator. * Any inherited class must overload the () operator. */ -class UnaryPredicate0D -{ -public: - bool result; - void *py_up0D; - - /*! Default constructor. */ - UnaryPredicate0D() - { - py_up0D = 0; - } - - /*! Destructor. */ - virtual ~UnaryPredicate0D() {} - - /*! Returns the string of the name of the UnaryPredicate0D. */ - virtual string getName() const - { - return "UnaryPredicate0D"; - } - - /*! The () operator. Must be overload by inherited classes. - * \param it: - * The Interface0DIterator pointing onto the Interface0D at which we wish to evaluate the predicate. - * \return true if the condition is satisfied, false otherwise. - */ - virtual int operator()(Interface0DIterator& it); +class UnaryPredicate0D { + public: + bool result; + void *py_up0D; + + /*! Default constructor. */ + UnaryPredicate0D() + { + py_up0D = 0; + } + + /*! Destructor. */ + virtual ~UnaryPredicate0D() + { + } + + /*! Returns the string of the name of the UnaryPredicate0D. */ + virtual string getName() const + { + return "UnaryPredicate0D"; + } + + /*! The () operator. Must be overload by inherited classes. + * \param it: + * The Interface0DIterator pointing onto the Interface0D at which we wish to evaluate the predicate. + * \return true if the condition is satisfied, false otherwise. + */ + virtual int operator()(Interface0DIterator &it); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryPredicate0D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryPredicate0D") #endif }; - // // BinaryPredicate0D (base class for predicates in 0D) // @@ -85,43 +85,43 @@ public: * It evaluates a relation between 2 Interface0D and returns true or false. * It is used by calling the () operator. */ -class BinaryPredicate0D -{ -public: - bool result; - void *py_bp0D; - - /*! Default constructor. */ - BinaryPredicate0D() - { - py_bp0D = 0; - } - - /*! Destructor. */ - virtual ~BinaryPredicate0D() {} - - /*! Returns the string of the name of the binary predicate. */ - virtual string getName() const - { - return "BinaryPredicate0D"; - } - - /*! The () operator. Must be overload by inherited classes. - * It evaluates a relation between 2 Interface0D. - * \param inter1: - * The first Interface0D. - * \param inter2: - * The second Interface0D. - * \return true or false. - */ - virtual int operator()(Interface0D& inter1, Interface0D& inter2); +class BinaryPredicate0D { + public: + bool result; + void *py_bp0D; + + /*! Default constructor. */ + BinaryPredicate0D() + { + py_bp0D = 0; + } + + /*! Destructor. */ + virtual ~BinaryPredicate0D() + { + } + + /*! Returns the string of the name of the binary predicate. */ + virtual string getName() const + { + return "BinaryPredicate0D"; + } + + /*! The () operator. Must be overload by inherited classes. + * It evaluates a relation between 2 Interface0D. + * \param inter1: + * The first Interface0D. + * \param inter2: + * The second Interface0D. + * \return true or false. + */ + virtual int operator()(Interface0D &inter1, Interface0D &inter2); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BinaryPredicate0D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BinaryPredicate0D") #endif }; - // // Predicates definitions // @@ -131,50 +131,52 @@ namespace Predicates0D { // TrueUP0D /*! Returns true any time */ -class TrueUP0D : public UnaryPredicate0D -{ -public: - /*! Default constructor. */ - TrueUP0D() {} - - /*! Returns the string "TrueUP0D"*/ - string getName() const - { - return "TrueUP0D"; - } - - /*! The () operator. */ - int operator()(Interface0DIterator&) - { - result = true; - return 0; - } +class TrueUP0D : public UnaryPredicate0D { + public: + /*! Default constructor. */ + TrueUP0D() + { + } + + /*! Returns the string "TrueUP0D"*/ + string getName() const + { + return "TrueUP0D"; + } + + /*! The () operator. */ + int operator()(Interface0DIterator &) + { + result = true; + return 0; + } }; // FalseUP0D /*! Returns false any time */ -class FalseUP0D : public UnaryPredicate0D -{ -public: - /*! Default constructor. */ - FalseUP0D() {} - - /*! Returns the string "FalseUP0D"*/ - string getName() const - { - return "FalseUP0D"; - } - - /*! The () operator. */ - int operator()(Interface0DIterator&) - { - result = false; - return 0; - } +class FalseUP0D : public UnaryPredicate0D { + public: + /*! Default constructor. */ + FalseUP0D() + { + } + + /*! Returns the string "FalseUP0D"*/ + string getName() const + { + return "FalseUP0D"; + } + + /*! The () operator. */ + int operator()(Interface0DIterator &) + { + result = false; + return 0; + } }; -} // end of namespace Predicates0D +} // end of namespace Predicates0D } /* namespace Freestyle */ -#endif // __FREESTYLE_PREDICATES_0D_H__ +#endif // __FREESTYLE_PREDICATES_0D_H__ diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.cpp b/source/blender/freestyle/intern/stroke/Predicates1D.cpp index b00443bf404..e3b3fefd448 100644 --- a/source/blender/freestyle/intern/stroke/Predicates1D.cpp +++ b/source/blender/freestyle/intern/stroke/Predicates1D.cpp @@ -24,14 +24,14 @@ namespace Freestyle { -int UnaryPredicate1D::operator()(Interface1D& inter) +int UnaryPredicate1D::operator()(Interface1D &inter) { - return Director_BPy_UnaryPredicate1D___call__(this, inter); + return Director_BPy_UnaryPredicate1D___call__(this, inter); } -int BinaryPredicate1D::operator()(Interface1D& inter1, Interface1D& inter2) +int BinaryPredicate1D::operator()(Interface1D &inter1, Interface1D &inter2) { - return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2); + return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h index 0501e33bcf0..be70907b51b 100644 --- a/source/blender/freestyle/intern/stroke/Predicates1D.h +++ b/source/blender/freestyle/intern/stroke/Predicates1D.h @@ -32,7 +32,7 @@ #include "../view_map/Functions1D.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -48,40 +48,40 @@ namespace Freestyle { * The UnaryPredicate1D is used by calling its () operator. * Any inherited class must overload the () operator. */ -class UnaryPredicate1D -{ -public: - bool result; - void *py_up1D; - - /*! Default constructor. */ - UnaryPredicate1D() - { - py_up1D = NULL; - } - - /*! Destructor. */ - virtual ~UnaryPredicate1D() {} - - /*! Returns the string of the name of the UnaryPredicate1D. */ - virtual string getName() const - { - return "UnaryPredicate1D"; - } - - /*! The () operator. Must be overload by inherited classes. - * \param inter: - * The Interface1D on which we wish to evaluate the predicate. - * \return true if the condition is satisfied, false otherwise. - */ - virtual int operator()(Interface1D& inter); +class UnaryPredicate1D { + public: + bool result; + void *py_up1D; + + /*! Default constructor. */ + UnaryPredicate1D() + { + py_up1D = NULL; + } + + /*! Destructor. */ + virtual ~UnaryPredicate1D() + { + } + + /*! Returns the string of the name of the UnaryPredicate1D. */ + virtual string getName() const + { + return "UnaryPredicate1D"; + } + + /*! The () operator. Must be overload by inherited classes. + * \param inter: + * The Interface1D on which we wish to evaluate the predicate. + * \return true if the condition is satisfied, false otherwise. + */ + virtual int operator()(Interface1D &inter); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryPredicate1D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryPredicate1D") #endif }; - // // BinaryPredicate1D (base class for predicates in 1D) // @@ -92,43 +92,43 @@ public: * It evaluates a relation between 2 Interface1D and returns true or false. * It is used by calling the () operator. */ -class BinaryPredicate1D -{ -public: - bool result; - void *py_bp1D; - - /*! Default constructor. */ - BinaryPredicate1D() - { - py_bp1D = NULL; - } - - /*! Destructor. */ - virtual ~BinaryPredicate1D() {} - - /*! Returns the string of the name of the binary predicate. */ - virtual string getName() const - { - return "BinaryPredicate1D"; - } - - /*! The () operator. Must be overload by inherited classes. - * It evaluates a relation between 2 Interface1D. - * \param inter1: - * The first Interface1D. - * \param inter2: - * The second Interface1D. - * \return true or false. - */ - virtual int operator()(Interface1D& inter1, Interface1D& inter2); +class BinaryPredicate1D { + public: + bool result; + void *py_bp1D; + + /*! Default constructor. */ + BinaryPredicate1D() + { + py_bp1D = NULL; + } + + /*! Destructor. */ + virtual ~BinaryPredicate1D() + { + } + + /*! Returns the string of the name of the binary predicate. */ + virtual string getName() const + { + return "BinaryPredicate1D"; + } + + /*! The () operator. Must be overload by inherited classes. + * It evaluates a relation between 2 Interface1D. + * \param inter1: + * The first Interface1D. + * \param inter2: + * The second Interface1D. + * \return true or false. + */ + virtual int operator()(Interface1D &inter1, Interface1D &inter2); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BinaryPredicate1D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BinaryPredicate1D") #endif }; - // // Predicates definitions // @@ -138,313 +138,311 @@ namespace Predicates1D { // TrueUP1D /*! Returns true */ -class TrueUP1D : public UnaryPredicate1D -{ -public: - /*! Constructor */ - TrueUP1D() {} - - /*! Returns the string "TrueUP1D"*/ - string getName() const - { - return "TrueUP1D"; - } - - /*! the () operator */ - int operator()(Interface1D&) - { - result = true; - return 0; - } +class TrueUP1D : public UnaryPredicate1D { + public: + /*! Constructor */ + TrueUP1D() + { + } + + /*! Returns the string "TrueUP1D"*/ + string getName() const + { + return "TrueUP1D"; + } + + /*! the () operator */ + int operator()(Interface1D &) + { + result = true; + return 0; + } }; // FalseUP1D /*! Returns false */ -class FalseUP1D : public UnaryPredicate1D -{ -public: - /*! Constructor */ - FalseUP1D() {} - - /*! Returns the string "FalseUP1D"*/ - string getName() const - { - return "FalseUP1D"; - } - - /*! the () operator */ - int operator()(Interface1D&) - { - result = false; - return 0; - } +class FalseUP1D : public UnaryPredicate1D { + public: + /*! Constructor */ + FalseUP1D() + { + } + + /*! Returns the string "FalseUP1D"*/ + string getName() const + { + return "FalseUP1D"; + } + + /*! the () operator */ + int operator()(Interface1D &) + { + result = false; + return 0; + } }; // QuantitativeInvisibilityUP1D /*! Returns true if the Quantitative Invisibility evaluated at an Interface1D, using the QuantitativeInvisibilityF1D * functor, equals a certain user-defined value. */ -class QuantitativeInvisibilityUP1D : public UnaryPredicate1D -{ -public: - /*! Builds the Predicate. - * \param qi: - * The Quantitative Invisibility you want the Interface1D to have - */ - QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) {} - - /*! Returns the string "QuantitativeInvisibilityUP1D" */ - string getName() const - { - return "QuantitativeInvisibilityUP1D"; - } - - /*! the () operator */ - int operator()(Interface1D& inter) - { - Functions1D::QuantitativeInvisibilityF1D func; - if (func(inter) < 0) - return -1; - result = (func.result == _qi); - return 0; - } - -private: - unsigned _qi; +class QuantitativeInvisibilityUP1D : public UnaryPredicate1D { + public: + /*! Builds the Predicate. + * \param qi: + * The Quantitative Invisibility you want the Interface1D to have + */ + QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) + { + } + + /*! Returns the string "QuantitativeInvisibilityUP1D" */ + string getName() const + { + return "QuantitativeInvisibilityUP1D"; + } + + /*! the () operator */ + int operator()(Interface1D &inter) + { + Functions1D::QuantitativeInvisibilityF1D func; + if (func(inter) < 0) + return -1; + result = (func.result == _qi); + return 0; + } + + private: + unsigned _qi; }; // ContourUP1D /*! Returns true if the Interface1D is a contour. * An Interface1D is a contour if it is borded by a different shape on each of its sides. */ -class ContourUP1D : public UnaryPredicate1D -{ -private: - Functions1D::CurveNatureF1D _getNature; - -public: - /*! Returns the string "ContourUP1D"*/ - string getName() const - { - return "ContourUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - if (_getNature(inter) < 0) - return -1; - if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) { - Interface0DIterator it = inter.verticesBegin(); - for (; !it.isEnd(); ++it) { - if (Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) { - result = true; - return 0; - } - } - } - result = false; - return 0; - } +class ContourUP1D : public UnaryPredicate1D { + private: + Functions1D::CurveNatureF1D _getNature; + + public: + /*! Returns the string "ContourUP1D"*/ + string getName() const + { + return "ContourUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + if (_getNature(inter) < 0) + return -1; + if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) { + Interface0DIterator it = inter.verticesBegin(); + for (; !it.isEnd(); ++it) { + if (Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } }; // ExternalContourUP1D /*! Returns true if the Interface1D is an external contour. * An Interface1D is an external contour if it is borded by no shape on one of its sides. */ -class ExternalContourUP1D : public UnaryPredicate1D -{ -private: - Functions1D::CurveNatureF1D _getNature; - -public: - /*! Returns the string "ExternalContourUP1D" */ - string getName() const - { - return "ExternalContourUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - if (_getNature(inter) < 0) - return -1; - if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) { - set<ViewShape*> occluded; - Functions1D::getOccludeeF1D(inter, occluded); - for (set<ViewShape*>::iterator os = occluded.begin(), osend = occluded.end(); os != osend; ++os) { - if ((*os) == 0) { - result = true; - return 0; - } - } - } - result = false; - return 0; - } +class ExternalContourUP1D : public UnaryPredicate1D { + private: + Functions1D::CurveNatureF1D _getNature; + + public: + /*! Returns the string "ExternalContourUP1D" */ + string getName() const + { + return "ExternalContourUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + if (_getNature(inter) < 0) + return -1; + if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) { + set<ViewShape *> occluded; + Functions1D::getOccludeeF1D(inter, occluded); + for (set<ViewShape *>::iterator os = occluded.begin(), osend = occluded.end(); os != osend; + ++os) { + if ((*os) == 0) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } }; // EqualToTimeStampUP1D /*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */ -class EqualToTimeStampUP1D : public UnaryPredicate1D -{ -protected: - unsigned _timeStamp; - -public: - EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D() - { - _timeStamp = ts; - } - - /*! Returns the string "EqualToTimeStampUP1D"*/ - string getName() const - { - return "EqualToTimeStampUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - result = (inter.getTimeStamp() == _timeStamp); - return 0; - } +class EqualToTimeStampUP1D : public UnaryPredicate1D { + protected: + unsigned _timeStamp; + + public: + EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D() + { + _timeStamp = ts; + } + + /*! Returns the string "EqualToTimeStampUP1D"*/ + string getName() const + { + return "EqualToTimeStampUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + result = (inter.getTimeStamp() == _timeStamp); + return 0; + } }; // EqualToChainingTimeStampUP1D /*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */ -class EqualToChainingTimeStampUP1D : public UnaryPredicate1D -{ -protected: - unsigned _timeStamp; - -public: - EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D() - { - _timeStamp = ts; - } - - /*! Returns the string "EqualToChainingTimeStampUP1D"*/ - string getName() const - { - return "EqualToChainingTimeStampUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - ViewEdge *edge = dynamic_cast<ViewEdge*>(&inter); - if (!edge) { - result = false; - return 0; - } - result = (edge->getChainingTimeStamp() >= _timeStamp); - return 0; - } +class EqualToChainingTimeStampUP1D : public UnaryPredicate1D { + protected: + unsigned _timeStamp; + + public: + EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D() + { + _timeStamp = ts; + } + + /*! Returns the string "EqualToChainingTimeStampUP1D"*/ + string getName() const + { + return "EqualToChainingTimeStampUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + ViewEdge *edge = dynamic_cast<ViewEdge *>(&inter); + if (!edge) { + result = false; + return 0; + } + result = (edge->getChainingTimeStamp() >= _timeStamp); + return 0; + } }; // ShapeUP1D /*! Returns true if the shape to which the Interface1D belongs to has the same Id as the one specified by the user. */ -class ShapeUP1D: public UnaryPredicate1D -{ -private: - Id _id; - -public: - /*! Builds the Predicate. - * \param idFirst: - * The first Id component. - * \param idSecond: - * The second Id component. - */ - ShapeUP1D(unsigned idFirst, unsigned idSecond = 0) : UnaryPredicate1D() - { - _id = Id(idFirst, idSecond); - } - - /*! Returns the string "ShapeUP1D"*/ - string getName() const - { - return "ShapeUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - set<ViewShape*> shapes; - Functions1D::getShapeF1D(inter, shapes); - for (set<ViewShape*>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) { - if ((*s)->getId() == _id) { - result = true; - return 0; - } - } - result = false; - return 0; - } +class ShapeUP1D : public UnaryPredicate1D { + private: + Id _id; + + public: + /*! Builds the Predicate. + * \param idFirst: + * The first Id component. + * \param idSecond: + * The second Id component. + */ + ShapeUP1D(unsigned idFirst, unsigned idSecond = 0) : UnaryPredicate1D() + { + _id = Id(idFirst, idSecond); + } + + /*! Returns the string "ShapeUP1D"*/ + string getName() const + { + return "ShapeUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + set<ViewShape *> shapes; + Functions1D::getShapeF1D(inter, shapes); + for (set<ViewShape *>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) { + if ((*s)->getId() == _id) { + result = true; + return 0; + } + } + result = false; + return 0; + } }; // WithinImageBoundaryUP1D /*! Returns true if the Interface1D is (partly) within the image boundary. */ -class WithinImageBoundaryUP1D: public UnaryPredicate1D -{ -private: - real _xmin, _ymin, _xmax, _ymax; - -public: - /*! Builds the Predicate. - * \param xmin: - * The X lower bound of the image boundary. - * \param ymin: - * The Y lower bound of the image boundary. - * \param xmax: - * The X upper bound of the image boundary. - * \param ymax: - * The Y upper bound of the image boundary. - */ - WithinImageBoundaryUP1D(const real xmin, const real ymin, const real xmax, const real ymax) - : _xmin(xmin), _ymin(ymin), _xmax(xmax), _ymax(ymax) - { - } - - /*! Returns the string "WithinImageBoundaryUP1D" */ - string getName() const - { - return "WithinImageBoundaryUP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& inter) - { - // 1st pass: check if a point is within the image boundary. - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) { - real x = (*it).getProjectedX(); - real y = (*it).getProjectedY(); - if (_xmin <= x && x <= _xmax && _ymin <= y && y <= _ymax) { - result = true; - return 0; - } - } - // 2nd pass: check if a line segment intersects with the image boundary. - it = inter.verticesBegin(); - if (it != itend) { - Vec2r pmin(_xmin, _ymin); - Vec2r pmax(_xmax, _ymax); - Vec2r prev((*it).getPoint2D()); - ++it; - for (; it != itend; ++it) { - Vec2r p((*it).getPoint2D()); - if (GeomUtils::intersect2dSeg2dArea (pmin, pmax, prev, p)) { - result = true; - return 0; - } - prev = p; - } - } - result = false; - return 0; - } +class WithinImageBoundaryUP1D : public UnaryPredicate1D { + private: + real _xmin, _ymin, _xmax, _ymax; + + public: + /*! Builds the Predicate. + * \param xmin: + * The X lower bound of the image boundary. + * \param ymin: + * The Y lower bound of the image boundary. + * \param xmax: + * The X upper bound of the image boundary. + * \param ymax: + * The Y upper bound of the image boundary. + */ + WithinImageBoundaryUP1D(const real xmin, const real ymin, const real xmax, const real ymax) + : _xmin(xmin), _ymin(ymin), _xmax(xmax), _ymax(ymax) + { + } + + /*! Returns the string "WithinImageBoundaryUP1D" */ + string getName() const + { + return "WithinImageBoundaryUP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &inter) + { + // 1st pass: check if a point is within the image boundary. + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + real x = (*it).getProjectedX(); + real y = (*it).getProjectedY(); + if (_xmin <= x && x <= _xmax && _ymin <= y && y <= _ymax) { + result = true; + return 0; + } + } + // 2nd pass: check if a line segment intersects with the image boundary. + it = inter.verticesBegin(); + if (it != itend) { + Vec2r pmin(_xmin, _ymin); + Vec2r pmax(_xmax, _ymax); + Vec2r prev((*it).getPoint2D()); + ++it; + for (; it != itend; ++it) { + Vec2r p((*it).getPoint2D()); + if (GeomUtils::intersect2dSeg2dArea(pmin, pmax, prev, p)) { + result = true; + return 0; + } + prev = p; + } + } + result = false; + return 0; + } }; // @@ -454,129 +452,125 @@ public: // TrueBP1D /*! Returns true. */ -class TrueBP1D : public BinaryPredicate1D -{ -public: - /*! Returns the string "TrueBP1D" */ - string getName() const - { - return "TrueBP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/) - { - result = true; - return 0; - } +class TrueBP1D : public BinaryPredicate1D { + public: + /*! Returns the string "TrueBP1D" */ + string getName() const + { + return "TrueBP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D & /*i1*/, Interface1D & /*i2*/) + { + result = true; + return 0; + } }; // FalseBP1D /*! Returns false. */ -class FalseBP1D : public BinaryPredicate1D -{ -public: - /*! Returns the string "FalseBP1D" */ - string getName() const - { - return "FalseBP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& /*i1*/, Interface1D& /*i2*/) - { - result = false; - return 0; - } +class FalseBP1D : public BinaryPredicate1D { + public: + /*! Returns the string "FalseBP1D" */ + string getName() const + { + return "FalseBP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D & /*i1*/, Interface1D & /*i2*/) + { + result = false; + return 0; + } }; // Length2DBP1D /*! Returns true if the 2D length of the Interface1D i1 is less than the 2D length of the Interface1D i2. */ -class Length2DBP1D : public BinaryPredicate1D -{ -public: - /*! Returns the string "Length2DBP1D" */ - string getName() const - { - return "Length2DBP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& i1, Interface1D& i2) - { - result = (i1.getLength2D() > i2.getLength2D()); - return 0; - } +class Length2DBP1D : public BinaryPredicate1D { + public: + /*! Returns the string "Length2DBP1D" */ + string getName() const + { + return "Length2DBP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &i1, Interface1D &i2) + { + result = (i1.getLength2D() > i2.getLength2D()); + return 0; + } }; // SameShapeIdBP1D /*! Returns true if the Interface1D i1 and i2 belong to the same shape. */ -class SameShapeIdBP1D : public BinaryPredicate1D -{ -public: - /*! Returns the string "SameShapeIdBP1D" */ - string getName() const - { - return "SameShapeIdBP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& i1, Interface1D& i2) - { - set<ViewShape*> shapes1; - Functions1D::getShapeF1D(i1, shapes1); - set<ViewShape*> shapes2; - Functions1D::getShapeF1D(i2, shapes2); - // FIXME:// n2 algo, can do better... - for (set<ViewShape*>::iterator s = shapes1.begin(), send = shapes1.end(); s != send; ++s) { - Id current = (*s)->getId(); - for (set<ViewShape*>::iterator s2 = shapes2.begin(), s2end = shapes2.end(); s2 != s2end; ++s2) { - if ((*s2)->getId() == current) { - result = true; - return 0; - } - } - } - result = false; - return 0; - } +class SameShapeIdBP1D : public BinaryPredicate1D { + public: + /*! Returns the string "SameShapeIdBP1D" */ + string getName() const + { + return "SameShapeIdBP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &i1, Interface1D &i2) + { + set<ViewShape *> shapes1; + Functions1D::getShapeF1D(i1, shapes1); + set<ViewShape *> shapes2; + Functions1D::getShapeF1D(i2, shapes2); + // FIXME:// n2 algo, can do better... + for (set<ViewShape *>::iterator s = shapes1.begin(), send = shapes1.end(); s != send; ++s) { + Id current = (*s)->getId(); + for (set<ViewShape *>::iterator s2 = shapes2.begin(), s2end = shapes2.end(); s2 != s2end; + ++s2) { + if ((*s2)->getId() == current) { + result = true; + return 0; + } + } + } + result = false; + return 0; + } }; // ViewMapGradientNormBP1D /*! Returns true if the evaluation of the Gradient norm Function is higher for Interface1D i1 than for i2. */ -class ViewMapGradientNormBP1D : public BinaryPredicate1D -{ -private: - Functions1D::GetViewMapGradientNormF1D _func; - -public: - ViewMapGradientNormBP1D(int level, IntegrationType iType = MEAN, float sampling = 2.0) - : BinaryPredicate1D(), _func(level, iType, sampling) - { - } - - /*! Returns the string "ViewMapGradientNormBP1D" */ - string getName() const - { - return "ViewMapGradientNormBP1D"; - } - - /*! The () operator. */ - int operator()(Interface1D& i1, Interface1D& i2) - { - if (_func(i1) < 0) - return -1; - real n1 = _func.result; - if (_func(i2) < 0) - return -1; - real n2 = _func.result; - result = (n1 > n2); - return 0; - } +class ViewMapGradientNormBP1D : public BinaryPredicate1D { + private: + Functions1D::GetViewMapGradientNormF1D _func; + + public: + ViewMapGradientNormBP1D(int level, IntegrationType iType = MEAN, float sampling = 2.0) + : BinaryPredicate1D(), _func(level, iType, sampling) + { + } + + /*! Returns the string "ViewMapGradientNormBP1D" */ + string getName() const + { + return "ViewMapGradientNormBP1D"; + } + + /*! The () operator. */ + int operator()(Interface1D &i1, Interface1D &i2) + { + if (_func(i1) < 0) + return -1; + real n1 = _func.result; + if (_func(i2) < 0) + return -1; + real n2 = _func.result; + result = (n1 > n2); + return 0; + } }; -} // end of namespace Predicates1D +} // end of namespace Predicates1D } /* namespace Freestyle */ -#endif // __FREESTYLE_PREDICATES_1D_H__ +#endif // __FREESTYLE_PREDICATES_1D_H__ diff --git a/source/blender/freestyle/intern/stroke/QInformationMap.h b/source/blender/freestyle/intern/stroke/QInformationMap.h index 7cb93321233..99393a8949c 100644 --- a/source/blender/freestyle/intern/stroke/QInformationMap.h +++ b/source/blender/freestyle/intern/stroke/QInformationMap.h @@ -28,37 +28,36 @@ namespace Freestyle { -class QInformationMap : public InformationMap -{ -private: - QImage _map; // the image or a piece of image - -public: - QInformationMap(); - QInformationMap(const QImage&); - QInformationMap(const QInformationMap&); - QInformationMap& operator=(const QInformationMap&); - - //float getSmoothedPixel(int x, int y, float sigma = 0.2f);1 - virtual float getMean(int x, int y); - virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance); - - inline const QImage& map() const - { - return _map; - } - - inline void setMap(const QImage& iMap, float iw, float ih) - { - _map = iMap.copy(); - _w = iw; - _h = ih; - } - -protected: - virtual float computeGaussian(int x, int y); +class QInformationMap : public InformationMap { + private: + QImage _map; // the image or a piece of image + + public: + QInformationMap(); + QInformationMap(const QImage &); + QInformationMap(const QInformationMap &); + QInformationMap &operator=(const QInformationMap &); + + //float getSmoothedPixel(int x, int y, float sigma = 0.2f);1 + virtual float getMean(int x, int y); + virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance); + + inline const QImage &map() const + { + return _map; + } + + inline void setMap(const QImage &iMap, float iw, float ih) + { + _map = iMap.copy(); + _w = iw; + _h = ih; + } + + protected: + virtual float computeGaussian(int x, int y); }; } /* namespace Freestyle */ -#endif // __FREESTYLE_Q_INFORMATION_MAP_H__ +#endif // __FREESTYLE_Q_INFORMATION_MAP_H__ diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp index 1cd363a15a5..7b6e53138bb 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.cpp +++ b/source/blender/freestyle/intern/stroke/Stroke.cpp @@ -39,276 +39,285 @@ namespace Freestyle { StrokeAttribute::StrokeAttribute() { - int i; - _alpha = 1.0f; - _thickness[0] = 1.0f; - _thickness[1] = 1.0f; - for (i = 0; i < 3; ++i) - _color[i] = 0.2f; - _color[0] = 0.8f; - _userAttributesReal = NULL; - _userAttributesVec2f = NULL; - _userAttributesVec3f = NULL; - _visible = true; -} - -StrokeAttribute::StrokeAttribute(const StrokeAttribute& iBrother) -{ - _alpha = iBrother._alpha; - _thickness[0] = iBrother._thickness[0]; - _thickness[1] = iBrother._thickness[1]; - for (int i = 0; i < 3; ++i) - _color[i] = iBrother._color[i]; - _visible = iBrother._visible; - if (iBrother._userAttributesReal) - _userAttributesReal = new realMap(*iBrother._userAttributesReal); - else - _userAttributesReal = NULL; - if (iBrother._userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f); - else - _userAttributesVec2f = NULL; - if (iBrother._userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f); - else - _userAttributesVec3f = NULL; -} - -StrokeAttribute::StrokeAttribute(float iRColor, float iGColor, float iBColor, float iAlpha, - float iRThickness, float iLThickness) -{ - _color[0] = iRColor; - _color[1] = iGColor; - _color[2] = iBColor; - - _alpha = iAlpha; - - _thickness[0] = iRThickness; - _thickness[1] = iLThickness; - - _visible = true; - - _userAttributesReal = NULL; - _userAttributesVec2f = NULL; - _userAttributesVec3f = NULL; -} - -StrokeAttribute::StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t) -{ - _alpha = (1 - t) * a1._alpha + t * a2._alpha; - _thickness[0] = (1 - t) * a1._thickness[0] + t * a2._thickness[0]; - _thickness[1] = (1 - t) * a1._thickness[1] + t * a2._thickness[1]; - for (int i = 0; i < 3; ++i) - _color[i] = (1 - t) * a1._color[i] + t * a2._color[i]; - - _visible = a1.isVisible(); - - // FIXME: to be checked (and enhanced) - if ((a1._userAttributesReal) && (a2._userAttributesReal)) { - if (a1._userAttributesReal->size() == a2._userAttributesReal->size()) { - _userAttributesReal = new realMap; - realMap::iterator it1 = a1._userAttributesReal->begin(), it1end = a1._userAttributesReal->end(); - realMap::iterator it2 = a2._userAttributesReal->begin(); - for (; it1 != it1end; ++it1, ++it2) { - (*_userAttributesReal)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); - } - } - } - else { - _userAttributesReal = NULL; - } - if ((a1._userAttributesVec2f) && (a2._userAttributesVec2f)) { - if (a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()) { - _userAttributesVec2f = new Vec2fMap; - Vec2fMap::iterator it1 = a1._userAttributesVec2f->begin(), it1end = a1._userAttributesVec2f->end(); - Vec2fMap::iterator it2 = a2._userAttributesVec2f->begin(); - for (; it1 != it1end; ++it1, ++it2) { - (*_userAttributesVec2f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); - } - } - } - else { - _userAttributesVec2f = NULL; - } - if ((a1._userAttributesVec3f) && (a2._userAttributesVec3f)) { - if (a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()) { - _userAttributesVec3f = new Vec3fMap; - Vec3fMap::iterator it1 = a1._userAttributesVec3f->begin(), it1end = a1._userAttributesVec3f->end(); - Vec3fMap::iterator it2 = a2._userAttributesVec3f->begin(); - for (; it1 != it1end; ++it1, ++it2) { - (*_userAttributesVec3f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); - } - } - } - else { - _userAttributesVec3f = NULL; - } + int i; + _alpha = 1.0f; + _thickness[0] = 1.0f; + _thickness[1] = 1.0f; + for (i = 0; i < 3; ++i) + _color[i] = 0.2f; + _color[0] = 0.8f; + _userAttributesReal = NULL; + _userAttributesVec2f = NULL; + _userAttributesVec3f = NULL; + _visible = true; +} + +StrokeAttribute::StrokeAttribute(const StrokeAttribute &iBrother) +{ + _alpha = iBrother._alpha; + _thickness[0] = iBrother._thickness[0]; + _thickness[1] = iBrother._thickness[1]; + for (int i = 0; i < 3; ++i) + _color[i] = iBrother._color[i]; + _visible = iBrother._visible; + if (iBrother._userAttributesReal) + _userAttributesReal = new realMap(*iBrother._userAttributesReal); + else + _userAttributesReal = NULL; + if (iBrother._userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f); + else + _userAttributesVec2f = NULL; + if (iBrother._userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f); + else + _userAttributesVec3f = NULL; +} + +StrokeAttribute::StrokeAttribute(float iRColor, + float iGColor, + float iBColor, + float iAlpha, + float iRThickness, + float iLThickness) +{ + _color[0] = iRColor; + _color[1] = iGColor; + _color[2] = iBColor; + + _alpha = iAlpha; + + _thickness[0] = iRThickness; + _thickness[1] = iLThickness; + + _visible = true; + + _userAttributesReal = NULL; + _userAttributesVec2f = NULL; + _userAttributesVec3f = NULL; +} + +StrokeAttribute::StrokeAttribute(const StrokeAttribute &a1, const StrokeAttribute &a2, float t) +{ + _alpha = (1 - t) * a1._alpha + t * a2._alpha; + _thickness[0] = (1 - t) * a1._thickness[0] + t * a2._thickness[0]; + _thickness[1] = (1 - t) * a1._thickness[1] + t * a2._thickness[1]; + for (int i = 0; i < 3; ++i) + _color[i] = (1 - t) * a1._color[i] + t * a2._color[i]; + + _visible = a1.isVisible(); + + // FIXME: to be checked (and enhanced) + if ((a1._userAttributesReal) && (a2._userAttributesReal)) { + if (a1._userAttributesReal->size() == a2._userAttributesReal->size()) { + _userAttributesReal = new realMap; + realMap::iterator it1 = a1._userAttributesReal->begin(), + it1end = a1._userAttributesReal->end(); + realMap::iterator it2 = a2._userAttributesReal->begin(); + for (; it1 != it1end; ++it1, ++it2) { + (*_userAttributesReal)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); + } + } + } + else { + _userAttributesReal = NULL; + } + if ((a1._userAttributesVec2f) && (a2._userAttributesVec2f)) { + if (a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()) { + _userAttributesVec2f = new Vec2fMap; + Vec2fMap::iterator it1 = a1._userAttributesVec2f->begin(), + it1end = a1._userAttributesVec2f->end(); + Vec2fMap::iterator it2 = a2._userAttributesVec2f->begin(); + for (; it1 != it1end; ++it1, ++it2) { + (*_userAttributesVec2f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); + } + } + } + else { + _userAttributesVec2f = NULL; + } + if ((a1._userAttributesVec3f) && (a2._userAttributesVec3f)) { + if (a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()) { + _userAttributesVec3f = new Vec3fMap; + Vec3fMap::iterator it1 = a1._userAttributesVec3f->begin(), + it1end = a1._userAttributesVec3f->end(); + Vec3fMap::iterator it2 = a2._userAttributesVec3f->begin(); + for (; it1 != it1end; ++it1, ++it2) { + (*_userAttributesVec3f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second); + } + } + } + else { + _userAttributesVec3f = NULL; + } } StrokeAttribute::~StrokeAttribute() { - if (_userAttributesReal) { - _userAttributesReal->clear(); - delete _userAttributesReal; - } - if (_userAttributesVec2f) { - _userAttributesVec2f->clear(); - delete _userAttributesVec2f; - } - if (_userAttributesVec3f) { - _userAttributesVec3f->clear(); - delete _userAttributesVec3f; - } -} - -StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute& iBrother) -{ - int i; - _alpha = iBrother._alpha; - _thickness[0] = iBrother._thickness[0]; - _thickness[1] = iBrother._thickness[1]; - for (i = 0; i < 3; ++i) - _color[i] = iBrother._color[i]; - _visible = iBrother._visible; - if (iBrother._userAttributesReal) { - if (!_userAttributesReal) - _userAttributesReal = new realMap; - _userAttributesReal = new realMap(*(iBrother._userAttributesReal)); - } - else { - _userAttributesReal = NULL; - } - if (iBrother._userAttributesVec2f) { - if (!_userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap; - _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f)); - } - else { - _userAttributesVec2f = NULL; - } - if (iBrother._userAttributesVec3f) { - if (!_userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap; - _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f)); - } - else { - _userAttributesVec3f = NULL; - } - return *this; + if (_userAttributesReal) { + _userAttributesReal->clear(); + delete _userAttributesReal; + } + if (_userAttributesVec2f) { + _userAttributesVec2f->clear(); + delete _userAttributesVec2f; + } + if (_userAttributesVec3f) { + _userAttributesVec3f->clear(); + delete _userAttributesVec3f; + } +} + +StrokeAttribute &StrokeAttribute::operator=(const StrokeAttribute &iBrother) +{ + int i; + _alpha = iBrother._alpha; + _thickness[0] = iBrother._thickness[0]; + _thickness[1] = iBrother._thickness[1]; + for (i = 0; i < 3; ++i) + _color[i] = iBrother._color[i]; + _visible = iBrother._visible; + if (iBrother._userAttributesReal) { + if (!_userAttributesReal) + _userAttributesReal = new realMap; + _userAttributesReal = new realMap(*(iBrother._userAttributesReal)); + } + else { + _userAttributesReal = NULL; + } + if (iBrother._userAttributesVec2f) { + if (!_userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap; + _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f)); + } + else { + _userAttributesVec2f = NULL; + } + if (iBrother._userAttributesVec3f) { + if (!_userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap; + _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f)); + } + else { + _userAttributesVec3f = NULL; + } + return *this; } float StrokeAttribute::getAttributeReal(const char *iName) const { - if (!_userAttributesReal) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no real attribute was defined" << endl; - } - return 0.0f; - } - realMap::iterator a = _userAttributesReal->find(iName); - if (a == _userAttributesReal->end()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl; - } - return 0.0f; - } - return (*a).second; + if (!_userAttributesReal) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no real attribute was defined" << endl; + } + return 0.0f; + } + realMap::iterator a = _userAttributesReal->find(iName); + if (a == _userAttributesReal->end()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no real attribute was added with the name " << iName + << endl; + } + return 0.0f; + } + return (*a).second; } Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const { - if (!_userAttributesVec2f) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl; - } - return 0; - } - Vec2fMap::iterator a = _userAttributesVec2f->find(iName); - if (a == _userAttributesVec2f->end()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName << endl; - } - return 0; - } - return (*a).second; + if (!_userAttributesVec2f) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl; + } + return 0; + } + Vec2fMap::iterator a = _userAttributesVec2f->find(iName); + if (a == _userAttributesVec2f->end()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName + << endl; + } + return 0; + } + return (*a).second; } Vec3f StrokeAttribute::getAttributeVec3f(const char *iName) const { - if (!_userAttributesVec3f) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl; - } - return 0; - } - Vec3fMap::iterator a = _userAttributesVec3f->find(iName); - if (a == _userAttributesVec3f->end()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName << endl; - } - return 0; - } - return (*a).second; + if (!_userAttributesVec3f) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl; + } + return 0; + } + Vec3fMap::iterator a = _userAttributesVec3f->find(iName); + if (a == _userAttributesVec3f->end()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName + << endl; + } + return 0; + } + return (*a).second; } bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const { - if (!_userAttributesReal) { - return false; - } - realMap::iterator a = _userAttributesReal->find(iName); - if (a == _userAttributesReal->end()) { - return false; - } - return true; + if (!_userAttributesReal) { + return false; + } + realMap::iterator a = _userAttributesReal->find(iName); + if (a == _userAttributesReal->end()) { + return false; + } + return true; } bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const { - if (!_userAttributesVec2f) { - return false; - } - Vec2fMap::iterator a = _userAttributesVec2f->find(iName); - if (a == _userAttributesVec2f->end()) { - return false; - } - return true; + if (!_userAttributesVec2f) { + return false; + } + Vec2fMap::iterator a = _userAttributesVec2f->find(iName); + if (a == _userAttributesVec2f->end()) { + return false; + } + return true; } bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const { - if (!_userAttributesVec3f) { - return false; - } - Vec3fMap::iterator a = _userAttributesVec3f->find(iName); - if (a == _userAttributesVec3f->end()) { - return false; - } - return true; + if (!_userAttributesVec3f) { + return false; + } + Vec3fMap::iterator a = _userAttributesVec3f->find(iName); + if (a == _userAttributesVec3f->end()) { + return false; + } + return true; } void StrokeAttribute::setAttributeReal(const char *iName, float att) { - if (!_userAttributesReal) - _userAttributesReal = new realMap; - (*_userAttributesReal)[iName] = att; + if (!_userAttributesReal) + _userAttributesReal = new realMap; + (*_userAttributesReal)[iName] = att; } -void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att) +void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f &att) { - if (!_userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap; - (*_userAttributesVec2f)[iName] = att; + if (!_userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap; + (*_userAttributesVec2f)[iName] = att; } -void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att) +void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f &att) { - if (!_userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap; - (*_userAttributesVec3f)[iName] = att; + if (!_userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap; + (*_userAttributesVec3f)[iName] = att; } - /**********************************/ /* */ /* */ @@ -319,59 +328,60 @@ void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att) StrokeVertex::StrokeVertex() : CurvePoint() { - _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } -StrokeVertex::StrokeVertex(const StrokeVertex& iBrother) : CurvePoint(iBrother) +StrokeVertex::StrokeVertex(const StrokeVertex &iBrother) : CurvePoint(iBrother) { - _Attribute = iBrother._Attribute; - _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; + _Attribute = iBrother._Attribute; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } StrokeVertex::StrokeVertex(SVertex *iSVertex) : CurvePoint(iSVertex, 0, 0.0f) { - _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } StrokeVertex::StrokeVertex(CurvePoint *iPoint) : CurvePoint(*iPoint) { - _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3) : CurvePoint(iA, iB, t3) { - // interpolate attributes: - _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3); - _CurvilignAbscissa = (1 - t3) * iA->curvilinearAbscissa() + t3 * iB->curvilinearAbscissa(); - _StrokeLength = iA->strokeLength(); + // interpolate attributes: + _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3); + _CurvilignAbscissa = (1 - t3) * iA->curvilinearAbscissa() + t3 * iB->curvilinearAbscissa(); + _StrokeLength = iA->strokeLength(); } -StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute) : CurvePoint(iSVertex, 0, 0.0f) +StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute &iAttribute) + : CurvePoint(iSVertex, 0, 0.0f) { - _Attribute = iAttribute; - _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; + _Attribute = iAttribute; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } -StrokeVertex::~StrokeVertex() {} +StrokeVertex::~StrokeVertex() +{ +} -StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother) +StrokeVertex &StrokeVertex::operator=(const StrokeVertex &iBrother) { - ((CurvePoint *)this)->operator=(iBrother); - _Attribute = iBrother._Attribute; + ((CurvePoint *)this)->operator=(iBrother); + _Attribute = iBrother._Attribute; - _CurvilignAbscissa = 0.0f; + _CurvilignAbscissa = 0.0f; - _StrokeLength = 0.0f; - return *this; + _StrokeLength = 0.0f; + return *this; } - - /**********************************/ /* */ /* */ @@ -382,437 +392,446 @@ StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother) Stroke::Stroke() { - _Length = 0; - _id = 0; - _sampling = FLT_MAX; - //_mediumType = DEFAULT_STROKE; - _mediumType = OPAQUE_MEDIUM; - _textureId = 0; - _textureStep = 1.0; - for (int a = 0; a < MAX_MTEX; a++) { - _mtex[a] = NULL; - } - _nodeTree = NULL; - _tips = false; - _rep = NULL; -} - -Stroke::Stroke(const Stroke& iBrother) -{ - for (vertex_container::const_iterator v = iBrother._Vertices.begin(), vend = iBrother._Vertices.end(); - v != vend; - v++) - { - _Vertices.push_back(*v); - } - _Length = 0; - _id = iBrother._id; - _ViewEdges = iBrother._ViewEdges; - _sampling = iBrother._sampling; - _mediumType = iBrother._mediumType; - _textureId = iBrother._textureId; - _textureStep = iBrother._textureStep; - for (int a = 0; a < MAX_MTEX; a++) { - _mtex[a] = iBrother._mtex[a]; - } - _nodeTree = iBrother._nodeTree; - _tips = iBrother._tips; - if (iBrother._rep) - _rep = new StrokeRep(*(iBrother._rep)); - else - _rep = NULL; + _Length = 0; + _id = 0; + _sampling = FLT_MAX; + //_mediumType = DEFAULT_STROKE; + _mediumType = OPAQUE_MEDIUM; + _textureId = 0; + _textureStep = 1.0; + for (int a = 0; a < MAX_MTEX; a++) { + _mtex[a] = NULL; + } + _nodeTree = NULL; + _tips = false; + _rep = NULL; +} + +Stroke::Stroke(const Stroke &iBrother) +{ + for (vertex_container::const_iterator v = iBrother._Vertices.begin(), + vend = iBrother._Vertices.end(); + v != vend; + v++) { + _Vertices.push_back(*v); + } + _Length = 0; + _id = iBrother._id; + _ViewEdges = iBrother._ViewEdges; + _sampling = iBrother._sampling; + _mediumType = iBrother._mediumType; + _textureId = iBrother._textureId; + _textureStep = iBrother._textureStep; + for (int a = 0; a < MAX_MTEX; a++) { + _mtex[a] = iBrother._mtex[a]; + } + _nodeTree = iBrother._nodeTree; + _tips = iBrother._tips; + if (iBrother._rep) + _rep = new StrokeRep(*(iBrother._rep)); + else + _rep = NULL; } Stroke::~Stroke() { - if (!_Vertices.empty()) { - for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; v++) { - delete (*v); - } - _Vertices.clear(); - } - - _ViewEdges.clear(); - if (_rep) { - delete _rep; - _rep = NULL; - } -} - -Stroke& Stroke::operator=(const Stroke& iBrother) -{ - if (!_Vertices.empty()) - _Vertices.clear(); - - for (vertex_container::const_iterator v = iBrother._Vertices.begin(), vend = iBrother._Vertices.end(); - v != vend; - v++) - { - _Vertices.push_back(*v); - } - _Length = iBrother._Length; - _id = iBrother._id; - _ViewEdges = iBrother._ViewEdges; - _sampling = iBrother._sampling; - if (_rep) - delete _rep; - if (iBrother._rep) - _rep = new StrokeRep(*(iBrother._rep)); - else - _rep = NULL; - return *this; + if (!_Vertices.empty()) { + for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; + v++) { + delete (*v); + } + _Vertices.clear(); + } + + _ViewEdges.clear(); + if (_rep) { + delete _rep; + _rep = NULL; + } +} + +Stroke &Stroke::operator=(const Stroke &iBrother) +{ + if (!_Vertices.empty()) + _Vertices.clear(); + + for (vertex_container::const_iterator v = iBrother._Vertices.begin(), + vend = iBrother._Vertices.end(); + v != vend; + v++) { + _Vertices.push_back(*v); + } + _Length = iBrother._Length; + _id = iBrother._id; + _ViewEdges = iBrother._ViewEdges; + _sampling = iBrother._sampling; + if (_rep) + delete _rep; + if (iBrother._rep) + _rep = new StrokeRep(*(iBrother._rep)); + else + _rep = NULL; + return *this; } void Stroke::setLength(float iLength) { - _Length = iLength; - for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; ++v) { - (*v)->setStrokeLength(iLength); - } + _Length = iLength; + for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; ++v) { + (*v)->setStrokeLength(iLength); + } } float Stroke::ComputeSampling(int iNVertices) { - if (iNVertices <= (int)_Vertices.size()) //soc - return _sampling; - - float sampling = _Length / (float)(iNVertices - _Vertices.size() + 1); - return sampling; -} - -class StrokeSegment -{ -public: - StrokeInternal::StrokeVertexIterator _begin; - StrokeInternal::StrokeVertexIterator _end; - float _length; - int _n; - float _sampling; - bool _resampled; - - StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, StrokeInternal::StrokeVertexIterator iend, - float ilength, int in, float isampling) - { - _begin = ibegin; - _end = iend; - _length = ilength; - _n = in; - _sampling = isampling; - _resampled = false; - } + if (iNVertices <= (int)_Vertices.size()) //soc + return _sampling; + + float sampling = _Length / (float)(iNVertices - _Vertices.size() + 1); + return sampling; +} + +class StrokeSegment { + public: + StrokeInternal::StrokeVertexIterator _begin; + StrokeInternal::StrokeVertexIterator _end; + float _length; + int _n; + float _sampling; + bool _resampled; + + StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, + StrokeInternal::StrokeVertexIterator iend, + float ilength, + int in, + float isampling) + { + _begin = ibegin; + _end = iend; + _length = ilength; + _n = in; + _sampling = isampling; + _resampled = false; + } }; int Stroke::Resample(int iNPoints) { - int NPointsToAdd = iNPoints - strokeVerticesSize(); - if (NPointsToAdd <= 0) - return 0; - - StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator next = it; - ++next; - StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); - - vertex_container newVertices; - real t = 0.0f; - StrokeVertex *newVertex = NULL; - vector<StrokeSegment> strokeSegments; - int N = 0; - float meanlength = 0; - int nsegments = 0; - while ((it != itend) && (next != itend)) { - Vec2r a((it)->getPoint()); - Vec2r b((next)->getPoint()); - Vec2r vec_tmp(b - a); - real norm_var = vec_tmp.norm(); - int numberOfPointsToAdd = (int)floor(NPointsToAdd * norm_var / _Length); - float csampling = norm_var / (float)(numberOfPointsToAdd + 1); - strokeSegments.push_back(StrokeSegment(it, next, norm_var, numberOfPointsToAdd, csampling)); - N += numberOfPointsToAdd; - meanlength += norm_var; - ++nsegments; - ++it; - ++next; - } - meanlength /= (float)nsegments; - - // if we don't have enough points let's resample finer some segments - bool checkEveryone = false; - bool resampled; - while (N < NPointsToAdd) { - resampled = false; - for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); s != send; ++s) { - if (s->_sampling == 0.0f) - continue; - - if (s->_resampled == false) { - if ((!checkEveryone) && (s->_length < meanlength)) - continue; - //resample - s->_n = s->_n + 1; - s->_sampling = s->_length / (float)(s->_n + 1); - s->_resampled = resampled = true; - N++; - if (N == NPointsToAdd) - break; - } - } - if (checkEveryone && !resampled) - break; - checkEveryone = true; - } - if (N < NPointsToAdd) { - // fatal error, likely because _Length is inconsistent with the stroke length computed with the vertices - return -1; - } - //actually resample: - for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); s != send; ++s) { - newVertices.push_back(&(*(s->_begin))); - if (s->_sampling < _sampling) - _sampling = s->_sampling; - - t = s->_sampling / s->_length; - for (int i = 0; i < s->_n; ++i) { - newVertex = new StrokeVertex(&(*(s->_begin)), &(*(s->_end)), t); - newVertices.push_back(newVertex); - t += s->_sampling / s->_length; - } - it = s->_begin; - next = s->_end; - } - - // add last: - ++it; - ++next; - if ((it != itend) && (next == itend)/* && (t == 0.0f)*/) - newVertices.push_back(&(*it)); - - int newsize = newVertices.size(); - if (newsize != iNPoints) - cerr << "Warning: incorrect points number" << endl; - - _Vertices.clear(); - _Vertices = newVertices; - newVertices.clear(); - - return 0; + int NPointsToAdd = iNPoints - strokeVerticesSize(); + if (NPointsToAdd <= 0) + return 0; + + StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator next = it; + ++next; + StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); + + vertex_container newVertices; + real t = 0.0f; + StrokeVertex *newVertex = NULL; + vector<StrokeSegment> strokeSegments; + int N = 0; + float meanlength = 0; + int nsegments = 0; + while ((it != itend) && (next != itend)) { + Vec2r a((it)->getPoint()); + Vec2r b((next)->getPoint()); + Vec2r vec_tmp(b - a); + real norm_var = vec_tmp.norm(); + int numberOfPointsToAdd = (int)floor(NPointsToAdd * norm_var / _Length); + float csampling = norm_var / (float)(numberOfPointsToAdd + 1); + strokeSegments.push_back(StrokeSegment(it, next, norm_var, numberOfPointsToAdd, csampling)); + N += numberOfPointsToAdd; + meanlength += norm_var; + ++nsegments; + ++it; + ++next; + } + meanlength /= (float)nsegments; + + // if we don't have enough points let's resample finer some segments + bool checkEveryone = false; + bool resampled; + while (N < NPointsToAdd) { + resampled = false; + for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); + s != send; + ++s) { + if (s->_sampling == 0.0f) + continue; + + if (s->_resampled == false) { + if ((!checkEveryone) && (s->_length < meanlength)) + continue; + //resample + s->_n = s->_n + 1; + s->_sampling = s->_length / (float)(s->_n + 1); + s->_resampled = resampled = true; + N++; + if (N == NPointsToAdd) + break; + } + } + if (checkEveryone && !resampled) + break; + checkEveryone = true; + } + if (N < NPointsToAdd) { + // fatal error, likely because _Length is inconsistent with the stroke length computed with the vertices + return -1; + } + //actually resample: + for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); + s != send; + ++s) { + newVertices.push_back(&(*(s->_begin))); + if (s->_sampling < _sampling) + _sampling = s->_sampling; + + t = s->_sampling / s->_length; + for (int i = 0; i < s->_n; ++i) { + newVertex = new StrokeVertex(&(*(s->_begin)), &(*(s->_end)), t); + newVertices.push_back(newVertex); + t += s->_sampling / s->_length; + } + it = s->_begin; + next = s->_end; + } + + // add last: + ++it; + ++next; + if ((it != itend) && (next == itend) /* && (t == 0.0f)*/) + newVertices.push_back(&(*it)); + + int newsize = newVertices.size(); + if (newsize != iNPoints) + cerr << "Warning: incorrect points number" << endl; + + _Vertices.clear(); + _Vertices = newVertices; + newVertices.clear(); + + return 0; } int Stroke::Resample(float iSampling) { - //cerr << "old size :" << strokeVerticesSize() << endl; - if (iSampling == 0) - return 0; - if (iSampling >= _sampling) - return 0; - - _sampling = iSampling; - // Resample... - //real curvilinearLength = 0.0f; - vertex_container newVertices; - real t = 0.0f; - const real limit = 0.99; - StrokeVertex *newVertex = NULL; - StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator next = it; - ++next; - StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); - while ((it != itend) && (next != itend)) { - newVertices.push_back(&(*it)); - Vec2r a((it)->getPoint()); - Vec2r b((next)->getPoint()); - Vec2r vec_tmp(b - a); - real norm_var = vec_tmp.norm(); - if (norm_var <= _sampling) { - //curvilinearLength += norm_var; - ++it; - ++next; - continue; - } - - //curvilinearLength += _sampling; - t = _sampling / norm_var; - while (t < limit) { - newVertex = new StrokeVertex(&(*it), &(*next), t); - //newVertex->setCurvilinearAbscissa(curvilinearLength); - newVertices.push_back(newVertex); - t = t + _sampling / norm_var; - } - ++it; - ++next; - } - // add last: - if ((it != itend) && (next == itend)/* && (t == 0.f)*/) - newVertices.push_back(&(*it)); - - _Vertices.clear(); - _Vertices = newVertices; - newVertices.clear(); - - return 0; + //cerr << "old size :" << strokeVerticesSize() << endl; + if (iSampling == 0) + return 0; + if (iSampling >= _sampling) + return 0; + + _sampling = iSampling; + // Resample... + //real curvilinearLength = 0.0f; + vertex_container newVertices; + real t = 0.0f; + const real limit = 0.99; + StrokeVertex *newVertex = NULL; + StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator next = it; + ++next; + StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); + while ((it != itend) && (next != itend)) { + newVertices.push_back(&(*it)); + Vec2r a((it)->getPoint()); + Vec2r b((next)->getPoint()); + Vec2r vec_tmp(b - a); + real norm_var = vec_tmp.norm(); + if (norm_var <= _sampling) { + //curvilinearLength += norm_var; + ++it; + ++next; + continue; + } + + //curvilinearLength += _sampling; + t = _sampling / norm_var; + while (t < limit) { + newVertex = new StrokeVertex(&(*it), &(*next), t); + //newVertex->setCurvilinearAbscissa(curvilinearLength); + newVertices.push_back(newVertex); + t = t + _sampling / norm_var; + } + ++it; + ++next; + } + // add last: + if ((it != itend) && (next == itend) /* && (t == 0.f)*/) + newVertices.push_back(&(*it)); + + _Vertices.clear(); + _Vertices = newVertices; + newVertices.clear(); + + return 0; } void Stroke::RemoveAllVertices() { - vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); - for (; it != itend; ++it) - delete (*it); - _Vertices.clear(); - UpdateLength(); + vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); + for (; it != itend; ++it) + delete (*it); + _Vertices.clear(); + UpdateLength(); } void Stroke::RemoveVertex(StrokeVertex *iVertex) { - vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); - for (; it != itend; ++it) { - if ((*it) == iVertex) { - delete iVertex; - it = _Vertices.erase(it); // it is now the element just after the erased element - break; - } - } - UpdateLength(); + vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); + for (; it != itend; ++it) { + if ((*it) == iVertex) { + delete iVertex; + it = _Vertices.erase(it); // it is now the element just after the erased element + break; + } + } + UpdateLength(); } void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next) { - vertex_container::iterator itnext = next.getIt(); - _Vertices.insert(itnext, iVertex); - UpdateLength(); + vertex_container::iterator itnext = next.getIt(); + _Vertices.insert(itnext, iVertex); + UpdateLength(); } void Stroke::UpdateLength() { - // recompute curvilinear abscissa and stroke length - float curvabsc = 0.0f; - vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); - vertex_container::iterator previous = it; - for (; it != itend; ++it) { - curvabsc += ((*it)->getPoint() - (*previous)->getPoint()).norm(); - (*it)->setCurvilinearAbscissa(curvabsc); - previous = it; - } - _Length = curvabsc; - for (it = _Vertices.begin(); it != itend; ++it) { - (*it)->setStrokeLength(_Length); - } + // recompute curvilinear abscissa and stroke length + float curvabsc = 0.0f; + vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); + vertex_container::iterator previous = it; + for (; it != itend; ++it) { + curvabsc += ((*it)->getPoint() - (*previous)->getPoint()).norm(); + (*it)->setCurvilinearAbscissa(curvabsc); + previous = it; + } + _Length = curvabsc; + for (it = _Vertices.begin(); it != itend; ++it) { + (*it)->setStrokeLength(_Length); + } } //! embedding vertex iterator Stroke::const_vertex_iterator Stroke::vertices_begin() const { - return const_vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end()); + return const_vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end()); } Stroke::const_vertex_iterator Stroke::vertices_end() const { - return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); + return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); } Stroke::vertex_iterator Stroke::vertices_end() { - return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); + return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); } StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesBegin(float t) { - if ((t != 0) && (t < _sampling)) - Resample(t); - return StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), - this->_Vertices.end()); + if ((t != 0) && (t < _sampling)) + Resample(t); + return StrokeInternal::StrokeVertexIterator( + this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end()); } StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() { - return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()); + return StrokeInternal::StrokeVertexIterator( + this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()); } Interface0DIterator Stroke::verticesBegin() { -Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), - this->_Vertices.end())); -return ret; + Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator( + this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end())); + return ret; } Interface0DIterator Stroke::verticesEnd() { - Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), - this->_Vertices.end())); - return ret; + Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator( + this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end())); + return ret; } Interface0DIterator Stroke::pointsBegin(float /*t*/) { - return verticesBegin(); // FIXME + return verticesBegin(); // FIXME } Interface0DIterator Stroke::pointsEnd(float /*t*/) { - return verticesEnd(); + return verticesEnd(); } void Stroke::ScaleThickness(float iFactor) { - for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; ++it) { - StrokeAttribute& attr = (*it)->attribute(); - attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL()); - } + for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; + ++it) { + StrokeAttribute &attr = (*it)->attribute(); + attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL()); + } } void Stroke::Render(const StrokeRenderer *iRenderer) { - if (!_rep) - _rep = new StrokeRep(this); - iRenderer->RenderStrokeRep(_rep); + if (!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRep(_rep); } void Stroke::RenderBasic(const StrokeRenderer *iRenderer) { - if (!_rep) - _rep = new StrokeRep(this); - iRenderer->RenderStrokeRep(_rep); + if (!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRep(_rep); } Stroke::vertex_iterator Stroke::vertices_begin(float sampling) { - // Resample if necessary - if ((sampling != 0) && (sampling < _sampling)) - Resample(sampling); - return vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end()); - //return _Vertices.begin(); + // Resample if necessary + if ((sampling != 0) && (sampling < _sampling)) + Resample(sampling); + return vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end()); + //return _Vertices.begin(); } #if 0 Stroke::vertex_iterator Stroke::vertices_last() { - vertex_iterator res = vertices_begin(); - vertex_iterator next = res; - ++next; - while (!next.end()) { - ++next; - ++res; - } - return res; + vertex_iterator res = vertices_begin(); + vertex_iterator next = res; + ++next; + while (!next.end()) { + ++next; + ++res; + } + return res; } Stroke::const_vertex_iterator Stroke::vertices_last() const { - const_vertex_iterator res = vertices_begin(); - const_vertex_iterator next = res; - ++next; - while (!next.end()) { - ++next; - ++res; - } - return res; + const_vertex_iterator res = vertices_begin(); + const_vertex_iterator next = res; + ++next; + while (!next.end()) { + ++next; + ++res; + } + return res; } Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling) { - // Resample if necessary - if (sampling < _sampling) - Resample(sampling); - return _Vertices.rbegin(); + // Resample if necessary + if (sampling < _sampling) + Resample(sampling); + return _Vertices.rbegin(); } @@ -820,146 +839,146 @@ inline Vec3r shaded_color(int iCombination = 0) const; inline Vec<3, real> Stroke::orientation2d(const_vertex_iterator it) const { - return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it); + return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it); } Vec3r Stroke::orientation2d(int iCombination) const { - return edge_orientation2d_function<Stroke>(*this, iCombination); + return edge_orientation2d_function<Stroke>(*this, iCombination); } inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const { - return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it); + return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it); } Vec3r Stroke::orientation3d(int iCombination) const { - return edge_orientation3d_function<Stroke>(*this, iCombination); + return edge_orientation3d_function<Stroke>(*this, iCombination); } Material Stroke::material() const { - const_vertex_iterator v = vertices_begin(), vend = strokeVerticesEnd(); - Material mat = (*v)->material(); - for (; v != vend; ++v) { - if (mat != (*v)->material()) - Exception::raiseException(); - } - return mat; + const_vertex_iterator v = vertices_begin(), vend = strokeVerticesEnd(); + Material mat = (*v)->material(); + for (; v != vend; ++v) { + if (mat != (*v)->material()) + Exception::raiseException(); + } + return mat; } int Stroke::qi() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - int qi_= (*v)->qi(); - for (; v != vend; ++v) { - if ((*v)->qi() != qi_) - Exception::raiseException(); - } - return qi_; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + int qi_= (*v)->qi(); + for (; v != vend; ++v) { + if ((*v)->qi() != qi_) + Exception::raiseException(); + } + return qi_; } inline occluder_container::const_iterator occluders_begin() const { - return _FEdgeA->occluders().begin(); + return _FEdgeA->occluders().begin(); } inline occluder_container::const_iterator occluders_end() const { - return _FEdgeA->occluders().end(); + return _FEdgeA->occluders().end(); } int Stroke::occluders_size() const { - return qi(); + return qi(); } bool Stroke::occluders_empty() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - bool empty = (*v)->occluders_empty(); - for (; v != vend; ++v) { - if ((*v)->occluders_empty() != empty) - Exception::raiseException(); - } - return empty; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + bool empty = (*v)->occluders_empty(); + for (; v != vend; ++v) { + if ((*v)->occluders_empty() != empty) + Exception::raiseException(); + } + return empty; } -#if 0 +# if 0 inline const polygon3d& occludee() const { - return *(_FEdgeA->aFace()); + return *(_FEdgeA->aFace()); } -#endif +# endif const SShape *Stroke::occluded_shape() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - const SShape *sshape = (*v)->occluded_shape(); - for (; v != vend; ++v) { - if ((*v)->occluded_shape() != sshape) - Exception::raiseException(); - } - return sshape; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + const SShape *sshape = (*v)->occluded_shape(); + for (; v != vend; ++v) { + if ((*v)->occluded_shape() != sshape) + Exception::raiseException(); + } + return sshape; } const bool Stroke::occludee_empty() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - bool empty = (*v)->occludee_empty(); - for (; v != vend; ++v) { - if ((*v)->occludee_empty() != empty) - Exception::raiseException(); - } - return empty; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + bool empty = (*v)->occludee_empty(); + for (; v != vend; ++v) { + if ((*v)->occludee_empty() != empty) + Exception::raiseException(); + } + return empty; } const SShape *Stroke::shape() const { - const_vertex_iterator v = vertices_begin(), vend = vertices_end(); - const SShape *sshape = (*v)->shape(); - for (; v != vend; ++v) { - if ((*v)->shape() != sshape) - Exception::raiseException(); - } - return sshape; + const_vertex_iterator v = vertices_begin(), vend = vertices_end(); + const SShape *sshape = (*v)->shape(); + for (; v != vend; ++v) { + if ((*v)->shape() != sshape) + Exception::raiseException(); + } + return sshape; } real Stroke::z_discontinuity(int iCombination) const { - return z_discontinuity_edge_function<Stroke>(*this, iCombination); + return z_discontinuity_edge_function<Stroke>(*this, iCombination); } Vec3r Stroke::curvature2d_as_vector(int iCombination) const { - return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination); + return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination); } real Stroke::curvature2d_as_angle(int iCombination) const { - return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination); + return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination); } float Stroke::shape_importance(int iCombination) const { - return shape_importance_edge_function<Stroke>(*this, iCombination); + return shape_importance_edge_function<Stroke>(*this, iCombination); } float Stroke::local_average_depth(int iCombination ) const { - return local_average_depth_edge_function<Stroke >(*this, iCombination); + return local_average_depth_edge_function<Stroke >(*this, iCombination); } float Stroke::local_depth_variance(int iCombination) const { - return local_depth_variance_edge_function<Stroke>(*this, iCombination); + return local_depth_variance_edge_function<Stroke>(*this, iCombination); } real Stroke::local_average_density(float sigma , int iCombination ) const { - return density_edge_function<Stroke>(*this, iCombination); + return density_edge_function<Stroke>(*this, iCombination); } #endif diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h index bc335b2252e..3eae5e91b6a 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.h +++ b/source/blender/freestyle/intern/stroke/Stroke.h @@ -34,7 +34,7 @@ #include "../system/StringUtils.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif extern "C" { @@ -43,7 +43,7 @@ struct bNodeTree; } #ifndef MAX_MTEX -#define MAX_MTEX 18 +# define MAX_MTEX 18 #endif namespace Freestyle { @@ -56,427 +56,428 @@ namespace Freestyle { /*! Class to define an attribute associated to a Stroke Vertex. * This attribute stores the color, alpha and thickness values for a Stroke Vertex. */ -class StrokeAttribute -{ -public: - /*! default constructor */ - StrokeAttribute(); - - /*! Copy constructor */ - StrokeAttribute(const StrokeAttribute& iBrother); - - /*! Builds a stroke vertex attribute from a set of parameters. - * \param iRColor: - * The Red Component value. - * \param iGColor: - * The Green Component value. - * \param iBColor: - * The Blue Component value. - * \param iAlpha: - * The transparency value - * \param iRThickness: - * The thickness of the stroke on the right - * \param iLThickness: - * The Thickness of the stroke on the left - */ - StrokeAttribute(float iRColor, float iGColor, float iBColor, float iAlpha, float iRThickness, float iLThickness); - - /*! Interpolation constructor. - * Builds a StrokeAttribute from two StrokeAttributes and an interpolation parameter. - * \param a1: - * The first Attribute. - * \param a2: - * The second parameter. - * \param t: - * The interpolation parameter. - */ - StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t); - - /*! destructor */ - virtual ~StrokeAttribute(); - - /* operators */ - /*! operator = */ - StrokeAttribute& operator=(const StrokeAttribute& iBrother); - - /* accessors */ - /*! Returns the attribute's color. - * \return The array of 3 floats containing the R,G,B values of the attribute's color. - */ - inline const float *getColor() const - { - return _color; - } - - /*! Returns the R color component. */ - inline const float getColorR() const - { - return _color[0]; - } - - /*! Returns the G color component. */ - inline const float getColorG() const - { - return _color[1]; - } - - /*! Returns the B color component. */ - inline const float getColorB() const - { - return _color[2]; - } - - /*! Returns the RGB color components. */ - inline Vec3f getColorRGB() const - { - return Vec3f(_color[0], _color[1], _color[2]); - } - - /*! Returns the alpha color component. */ - inline float getAlpha() const - { - return _alpha; - } - - /*! Returns the attribute's thickness. - * \return an array of 2 floats. the first value is the thickness on the right of the vertex when following - * the stroke, the second one is the thickness on the left. - */ - inline const float *getThickness() const - { - return _thickness; - } - - /*! Returns the thickness on the right of the vertex when following the stroke. */ - inline const float getThicknessR() const - { - return _thickness[0]; - } - - /*! Returns the thickness on the left of the vertex when following the stroke. */ - inline const float getThicknessL() const - { - return _thickness[1]; - } - - /*! Returns the thickness on the right and on the left of the vertex when following the stroke. */ - inline Vec2f getThicknessRL() const - { - return Vec2f(_thickness[0], _thickness[1]); - } - - /*! Returns true if the strokevertex is visible, false otherwise */ - inline bool isVisible() const - { - return _visible; - } - - /*! Returns an attribute of type real - * \param iName: - * The name of the attribute - */ - float getAttributeReal(const char *iName) const; - - /*! Returns an attribute of type Vec2f - * \param iName: - * The name of the attribute - */ - Vec2f getAttributeVec2f(const char *iName) const; - - /*! Returns an attribute of type Vec3f - * \param iName: - * The name of the attribute - */ - Vec3f getAttributeVec3f(const char *iName) const; - - /*! Checks whether the attribute iName is availbale */ - bool isAttributeAvailableReal(const char *iName) const; - - /*! Checks whether the attribute iName is availbale */ - bool isAttributeAvailableVec2f(const char *iName) const; - - /*! Checks whether the attribute iName is availbale */ - bool isAttributeAvailableVec3f(const char *iName) const; - - /* modifiers */ - /*! sets the attribute's color. - * \param r: - * The new R value. - * \param g: - * The new G value. - * \param b: - * The new B value. - */ - inline void setColor(float r, float g, float b) - { - _color[0] = r; - _color[1] = g; - _color[2] = b; - } - - /*! sets the attribute's color. - * \param iRGB: - * The new RGB values. - */ - inline void setColor(const Vec3f& iRGB) - { - _color[0] = iRGB[0]; - _color[1] = iRGB[1]; - _color[2] = iRGB[2]; - } - - /*! sets the attribute's alpha value. - * \param alpha: - * The new alpha value. - */ - inline void setAlpha(float alpha) - { - _alpha = alpha; - } - - /*! sets the attribute's thickness. - * \param tr: - * The thickness on the right of the vertex when following the stroke. - * \param tl: - * The thickness on the left of the vertex when following the stroke. - */ - inline void setThickness(float tr, float tl) - { - _thickness[0] = tr; - _thickness[1] = tl; - } - - /*! sets the attribute's thickness. - * \param tRL: - * The thickness on the right and on the left of the vertex when following the stroke. - */ - inline void setThickness(const Vec2f& tRL) - { - _thickness[0] = tRL[0]; - _thickness[1] = tRL[1]; - } - - /*! sets the visible flag. True means visible. */ - inline void setVisible(bool iVisible) - { - _visible = iVisible; - } - - /*! Adds a user defined attribute of type real - * If there is no attribute of name iName, it is added. - * Otherwise, the new value replaces the old one. - * \param iName: - * The name of the attribute - * \param att: - * The attribute's value - */ - void setAttributeReal(const char *iName, float att); - - /*! Adds a user defined attribute of type Vec2f - * If there is no attribute of name iName, it is added. - * Otherwise, the new value replaces the old one. - * \param iName: - * The name of the attribute - * \param att: - * The attribute's value - */ - void setAttributeVec2f(const char *iName, const Vec2f& att); - - /*! Adds a user defined attribute of type Vec3f - * If there is no attribute of name iName, it is added. - * Otherwise, the new value replaces the old one. - * \param iName: - * The name of the attribute - * \param att: - * The attribute's value - */ - void setAttributeVec3f(const char *iName, const Vec3f& att); - -private: - typedef std::map<const char *, float, StringUtils::ltstr> realMap; - typedef std::map<const char *, Vec2f, StringUtils::ltstr> Vec2fMap; - typedef std::map<const char *, Vec3f, StringUtils::ltstr> Vec3fMap; - - //! the color - float _color[3]; - //! alpha - float _alpha; - //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented) - float _thickness[2]; - bool _visible; - realMap *_userAttributesReal; - Vec2fMap *_userAttributesVec2f; - Vec3fMap *_userAttributesVec3f; +class StrokeAttribute { + public: + /*! default constructor */ + StrokeAttribute(); + + /*! Copy constructor */ + StrokeAttribute(const StrokeAttribute &iBrother); + + /*! Builds a stroke vertex attribute from a set of parameters. + * \param iRColor: + * The Red Component value. + * \param iGColor: + * The Green Component value. + * \param iBColor: + * The Blue Component value. + * \param iAlpha: + * The transparency value + * \param iRThickness: + * The thickness of the stroke on the right + * \param iLThickness: + * The Thickness of the stroke on the left + */ + StrokeAttribute(float iRColor, + float iGColor, + float iBColor, + float iAlpha, + float iRThickness, + float iLThickness); + + /*! Interpolation constructor. + * Builds a StrokeAttribute from two StrokeAttributes and an interpolation parameter. + * \param a1: + * The first Attribute. + * \param a2: + * The second parameter. + * \param t: + * The interpolation parameter. + */ + StrokeAttribute(const StrokeAttribute &a1, const StrokeAttribute &a2, float t); + + /*! destructor */ + virtual ~StrokeAttribute(); + + /* operators */ + /*! operator = */ + StrokeAttribute &operator=(const StrokeAttribute &iBrother); + + /* accessors */ + /*! Returns the attribute's color. + * \return The array of 3 floats containing the R,G,B values of the attribute's color. + */ + inline const float *getColor() const + { + return _color; + } + + /*! Returns the R color component. */ + inline const float getColorR() const + { + return _color[0]; + } + + /*! Returns the G color component. */ + inline const float getColorG() const + { + return _color[1]; + } + + /*! Returns the B color component. */ + inline const float getColorB() const + { + return _color[2]; + } + + /*! Returns the RGB color components. */ + inline Vec3f getColorRGB() const + { + return Vec3f(_color[0], _color[1], _color[2]); + } + + /*! Returns the alpha color component. */ + inline float getAlpha() const + { + return _alpha; + } + + /*! Returns the attribute's thickness. + * \return an array of 2 floats. the first value is the thickness on the right of the vertex when following + * the stroke, the second one is the thickness on the left. + */ + inline const float *getThickness() const + { + return _thickness; + } + + /*! Returns the thickness on the right of the vertex when following the stroke. */ + inline const float getThicknessR() const + { + return _thickness[0]; + } + + /*! Returns the thickness on the left of the vertex when following the stroke. */ + inline const float getThicknessL() const + { + return _thickness[1]; + } + + /*! Returns the thickness on the right and on the left of the vertex when following the stroke. */ + inline Vec2f getThicknessRL() const + { + return Vec2f(_thickness[0], _thickness[1]); + } + + /*! Returns true if the strokevertex is visible, false otherwise */ + inline bool isVisible() const + { + return _visible; + } + + /*! Returns an attribute of type real + * \param iName: + * The name of the attribute + */ + float getAttributeReal(const char *iName) const; + + /*! Returns an attribute of type Vec2f + * \param iName: + * The name of the attribute + */ + Vec2f getAttributeVec2f(const char *iName) const; + + /*! Returns an attribute of type Vec3f + * \param iName: + * The name of the attribute + */ + Vec3f getAttributeVec3f(const char *iName) const; + + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableReal(const char *iName) const; + + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableVec2f(const char *iName) const; + + /*! Checks whether the attribute iName is availbale */ + bool isAttributeAvailableVec3f(const char *iName) const; + + /* modifiers */ + /*! sets the attribute's color. + * \param r: + * The new R value. + * \param g: + * The new G value. + * \param b: + * The new B value. + */ + inline void setColor(float r, float g, float b) + { + _color[0] = r; + _color[1] = g; + _color[2] = b; + } + + /*! sets the attribute's color. + * \param iRGB: + * The new RGB values. + */ + inline void setColor(const Vec3f &iRGB) + { + _color[0] = iRGB[0]; + _color[1] = iRGB[1]; + _color[2] = iRGB[2]; + } + + /*! sets the attribute's alpha value. + * \param alpha: + * The new alpha value. + */ + inline void setAlpha(float alpha) + { + _alpha = alpha; + } + + /*! sets the attribute's thickness. + * \param tr: + * The thickness on the right of the vertex when following the stroke. + * \param tl: + * The thickness on the left of the vertex when following the stroke. + */ + inline void setThickness(float tr, float tl) + { + _thickness[0] = tr; + _thickness[1] = tl; + } + + /*! sets the attribute's thickness. + * \param tRL: + * The thickness on the right and on the left of the vertex when following the stroke. + */ + inline void setThickness(const Vec2f &tRL) + { + _thickness[0] = tRL[0]; + _thickness[1] = tRL[1]; + } + + /*! sets the visible flag. True means visible. */ + inline void setVisible(bool iVisible) + { + _visible = iVisible; + } + + /*! Adds a user defined attribute of type real + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName: + * The name of the attribute + * \param att: + * The attribute's value + */ + void setAttributeReal(const char *iName, float att); + + /*! Adds a user defined attribute of type Vec2f + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName: + * The name of the attribute + * \param att: + * The attribute's value + */ + void setAttributeVec2f(const char *iName, const Vec2f &att); + + /*! Adds a user defined attribute of type Vec3f + * If there is no attribute of name iName, it is added. + * Otherwise, the new value replaces the old one. + * \param iName: + * The name of the attribute + * \param att: + * The attribute's value + */ + void setAttributeVec3f(const char *iName, const Vec3f &att); + + private: + typedef std::map<const char *, float, StringUtils::ltstr> realMap; + typedef std::map<const char *, Vec2f, StringUtils::ltstr> Vec2fMap; + typedef std::map<const char *, Vec3f, StringUtils::ltstr> Vec3fMap; + + //! the color + float _color[3]; + //! alpha + float _alpha; + //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented) + float _thickness[2]; + bool _visible; + realMap *_userAttributesReal; + Vec2fMap *_userAttributesVec2f; + Vec3fMap *_userAttributesVec3f; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeAttribute") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeAttribute") #endif }; - // // StrokeVertex // //////////////////////////////////////////////////////// /*! Class to define a stroke vertex. */ -class StrokeVertex : public CurvePoint -{ -public: // Implementation of Interface0D - /*! Returns the string "StrokeVertex" */ - virtual string getExactTypeName() const - { - return "StrokeVertex"; - } - -private: - StrokeAttribute _Attribute; //! The attribute associated to the vertex - float _CurvilignAbscissa; //! the curvilign abscissa - float _StrokeLength; // stroke length - -public: - /*! default constructor */ - StrokeVertex(); - - /*! Copy constructor */ - StrokeVertex(const StrokeVertex& iBrother); - - /*! Builds a stroke vertex from a SVertex */ - StrokeVertex(SVertex *iSVertex); - - /*! Builds a stroke vertex from a CurvePoint */ - StrokeVertex(CurvePoint *iPoint); - - /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/ - StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3); - - /*! Builds a stroke from a view vertex and an attribute */ - StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute); - - /*! destructor */ - virtual ~StrokeVertex(); - - /* operators */ - /*! operator = */ - StrokeVertex& operator=(const StrokeVertex& iBrother); - - /* accessors */ - /*! Returns the 2D point x coordinate */ - inline real x() const - { - return _Point2d[0]; - } - - /*! Returns the 2D point y coordinate */ - inline real y() const - { - return _Point2d[1]; - } - - /*! Returns the 2D point coordinates as a Vec2r */ - inline Vec2r getPoint() const - { - return getPoint2D(); - } - - /*! Returns the ith 2D point coordinate (i=0 or 1)*/ - inline real operator[](const int i) const - { - return _Point2d[i]; - } - - /*! Returns the StrokeAttribute for this StrokeVertex */ - inline const StrokeAttribute& attribute() const - { - return _Attribute; - } - - /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */ - inline StrokeAttribute& attribute() - { - return _Attribute; - } - - /*! Returns the curvilinear abscissa */ - inline float curvilinearAbscissa() const - { - return _CurvilignAbscissa; - } - - /*! Returns the length of the Stroke to which this StrokeVertex belongs */ - inline float strokeLength() const - { - return _StrokeLength; - } - - /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */ - inline float u() const - { - return _CurvilignAbscissa / _StrokeLength; - } - - /* modifiers */ - /*! sets the 2D x value */ - inline void setX(real x) - { - _Point2d[0] = x; - } - - /*! sets the 2D y value */ - inline void setY(real y) - { - _Point2d[1] = y; - } - - /*! sets the 2D x and y values */ - inline void setPoint(real x, real y) - { - _Point2d[0] = x; - _Point2d[1] = y; - } - - /*! sets the 2D x and y values */ - inline void setPoint(const Vec2r& p) - { - _Point2d[0] = p[0]; - _Point2d[1] = p[1]; - } - - /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */ - inline real& operator[](const int i) - { - return _Point2d[i]; - } - - /*! sets the attribute. */ - inline void setAttribute(const StrokeAttribute& iAttribute) - { - _Attribute = iAttribute; - } - - /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */ - inline void setCurvilinearAbscissa(float iAbscissa) - { - _CurvilignAbscissa = iAbscissa; - } - - /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't change the real - * Stroke's length.) - */ - inline void setStrokeLength(float iLength) - { - _StrokeLength = iLength; - } - - /* interface definition */ - /* inherited */ +class StrokeVertex : public CurvePoint { + public: // Implementation of Interface0D + /*! Returns the string "StrokeVertex" */ + virtual string getExactTypeName() const + { + return "StrokeVertex"; + } + + private: + StrokeAttribute _Attribute; //! The attribute associated to the vertex + float _CurvilignAbscissa; //! the curvilign abscissa + float _StrokeLength; // stroke length + + public: + /*! default constructor */ + StrokeVertex(); + + /*! Copy constructor */ + StrokeVertex(const StrokeVertex &iBrother); + + /*! Builds a stroke vertex from a SVertex */ + StrokeVertex(SVertex *iSVertex); + + /*! Builds a stroke vertex from a CurvePoint */ + StrokeVertex(CurvePoint *iPoint); + + /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/ + StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3); + + /*! Builds a stroke from a view vertex and an attribute */ + StrokeVertex(SVertex *iSVertex, const StrokeAttribute &iAttribute); + + /*! destructor */ + virtual ~StrokeVertex(); + + /* operators */ + /*! operator = */ + StrokeVertex &operator=(const StrokeVertex &iBrother); + + /* accessors */ + /*! Returns the 2D point x coordinate */ + inline real x() const + { + return _Point2d[0]; + } + + /*! Returns the 2D point y coordinate */ + inline real y() const + { + return _Point2d[1]; + } + + /*! Returns the 2D point coordinates as a Vec2r */ + inline Vec2r getPoint() const + { + return getPoint2D(); + } + + /*! Returns the ith 2D point coordinate (i=0 or 1)*/ + inline real operator[](const int i) const + { + return _Point2d[i]; + } + + /*! Returns the StrokeAttribute for this StrokeVertex */ + inline const StrokeAttribute &attribute() const + { + return _Attribute; + } + + /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */ + inline StrokeAttribute &attribute() + { + return _Attribute; + } + + /*! Returns the curvilinear abscissa */ + inline float curvilinearAbscissa() const + { + return _CurvilignAbscissa; + } + + /*! Returns the length of the Stroke to which this StrokeVertex belongs */ + inline float strokeLength() const + { + return _StrokeLength; + } + + /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */ + inline float u() const + { + return _CurvilignAbscissa / _StrokeLength; + } + + /* modifiers */ + /*! sets the 2D x value */ + inline void setX(real x) + { + _Point2d[0] = x; + } + + /*! sets the 2D y value */ + inline void setY(real y) + { + _Point2d[1] = y; + } + + /*! sets the 2D x and y values */ + inline void setPoint(real x, real y) + { + _Point2d[0] = x; + _Point2d[1] = y; + } + + /*! sets the 2D x and y values */ + inline void setPoint(const Vec2r &p) + { + _Point2d[0] = p[0]; + _Point2d[1] = p[1]; + } + + /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */ + inline real &operator[](const int i) + { + return _Point2d[i]; + } + + /*! sets the attribute. */ + inline void setAttribute(const StrokeAttribute &iAttribute) + { + _Attribute = iAttribute; + } + + /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */ + inline void setCurvilinearAbscissa(float iAbscissa) + { + _CurvilignAbscissa = iAbscissa; + } + + /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't change the real + * Stroke's length.) + */ + inline void setStrokeLength(float iLength) + { + _StrokeLength = iLength; + } + + /* interface definition */ + /* inherited */ #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertex") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertex") #endif }; - // // Stroke // @@ -492,400 +493,404 @@ class vertex_nonconst_traits; template<class Traits> class vertex_iterator_base; class StrokeVertexIterator; -} // end of namespace StrokeInternal +} // end of namespace StrokeInternal /*! Class to define a stroke. * A stroke is made of a set of 2D vertices (StrokeVertex), regularly spaced out. * This set of vertices defines the stroke's backbone geometry. * Each of these stroke vertices defines the stroke's shape and appearance at this vertex position. */ -class Stroke : public Interface1D -{ -public: // Implementation of Interface1D - /*! Returns the string "Stroke" */ - virtual string getExactTypeName() const - { - return "Stroke"; - } - - // Data access methods - - /*! Returns the Id of the Stroke */ - virtual Id getId() const - { - return _id; - } - - /*! The different blending modes available to similate the interaction media-medium. */ - typedef enum { - DRY_MEDIUM, /*!< To simulate a dry medium such as Pencil or Charcoal.*/ - HUMID_MEDIUM, /*!< To simulate ink painting (color subtraction blending).*/ - OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/ - } MediumType; - -public: - typedef std::deque<StrokeVertex*> vertex_container; // the vertices container - typedef std::vector<ViewEdge*> viewedge_container; // the viewedges container - typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits > vertex_iterator; - typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> const_vertex_iterator; - -public: - //typedef StrokeVertex vertex_type; - -private: - vertex_container _Vertices; //! The stroke's backbone vertices - Id _id; - float _Length; // The stroke length - viewedge_container _ViewEdges; - float _sampling; - float _textureStep; - // StrokeRenderer *_renderer; // mark implementation OpenGL renderer - MediumType _mediumType; - unsigned int _textureId; - MTex *_mtex[MAX_MTEX]; - bNodeTree *_nodeTree; - bool _tips; - StrokeRep *_rep; - Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity - -public: - /*! default constructor */ - Stroke(); - - /*! copy constructor */ - Stroke(const Stroke& iBrother); - - /*! Builds a stroke from a set of StrokeVertex. - * This constructor is templated by an iterator type. - * This iterator type must allow the vertices parsing using the ++ operator. - * \param iBegin: - * The iterator pointing to the first vertex. - * \param iEnd: - * The iterator pointing to the end of the vertex list. - */ - template<class InputVertexIterator> - Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd); - - /*! Destructor */ - virtual ~Stroke(); - - /* operators */ - /*! operator = */ - Stroke& operator=(const Stroke& iBrother); - - /*! Compute the sampling needed to get iNVertices vertices. - * If the specified number of vertices is less than the actual number of vertices, the actual sampling value - * is returned. (To remove Vertices, use the RemoveVertex() method of this class). - * \param iNVertices: - * The number of StrokeVertices we eventually want in our Stroke. - * \return the sampling that must be used in the Resample(float) method. - * \see Resample(int) - * \see Resample(float) - */ - float ComputeSampling(int iNVertices); - - /*! Resampling method. - * Resamples the curve so that it eventually has iNPoints. That means it is going to add iNPoints-vertices_size, - * if vertices_size is the number of points we already have. - * If vertices_size >= iNPoints, no resampling is done. - * \param iNPoints: - * The number of vertices we eventually want in our stroke. - */ - int Resample(int iNPoints); - - /*! Resampling method. - * Resamples the curve with a given sampling. - * If this sampling is < to the actual sampling value, no resampling is done. - * \param iSampling: - * The new sampling value. - */ - int Resample(float iSampling); - - /*! Removes all vertices from the Stroke. - */ - void RemoveAllVertices(); - - /*! Removes the stroke vertex iVertex - * from the stroke. - * The length and curvilinear abscissa are updated - * consequently. - */ - void RemoveVertex(StrokeVertex *iVertex); - - /*! Inserts the stroke vertex iVertex in the stroke before next. - * The length, curvilinear abscissa are updated consequently. - * \param iVertex: - * The StrokeVertex to insert in the Stroke. - * \param next: - * A StrokeVertexIterator pointing to the StrokeVeretx before which iVertex must be inserted. - */ - void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next); - - /*! Updates the 2D length of the Stroke */ - void UpdateLength(); - - /* Render method */ - void ScaleThickness(float iFactor); - void Render(const StrokeRenderer *iRenderer); - void RenderBasic(const StrokeRenderer *iRenderer); - - /* Iterator definition */ - - /* accessors */ - /*! Returns the 2D length of the Stroke */ - inline real getLength2D() const - { - return _Length; - } - - /*! Returns a reference to the time stamp value of the stroke. */ - /*! Returns the MediumType used for this Stroke. */ - inline MediumType getMediumType() const - { - return _mediumType; - } - - /*! Returns the id of the texture used to simulate th marks system for this Stroke */ - inline unsigned int getTextureId() {return _textureId;} - - /*! Returns the spacing of texture coordinates along the stroke lenght */ - inline float getTextureStep() {return _textureStep;} - - /*! Returns the texture used at given index to simulate the marks system for this Stroke */ - inline MTex *getMTex(int idx) { - return _mtex[idx]; - } - - /*! Return the shader node tree to define textures. */ - inline bNodeTree *getNodeTree() - { - return _nodeTree; - } - - /*! Returns true if this Stroke has textures assigned, false otherwise. */ - inline bool hasTex() const - { - return (_mtex[0] != NULL) || _nodeTree; - } - - /*! Returns true if this Stroke uses a texture with tips, false otherwise. */ - inline bool hasTips() const - { - return _tips; - } - - /* these advanced iterators are used only in C++ */ - inline int vertices_size() const - { - return _Vertices.size(); - } - - inline viewedge_container::const_iterator viewedges_begin() const - { - return _ViewEdges.begin(); - } - - inline viewedge_container::iterator viewedges_begin() - { - return _ViewEdges.begin(); - } - - inline viewedge_container::const_iterator viewedges_end() const - { - return _ViewEdges.end(); - } - - inline viewedge_container::iterator viewedges_end() - { - return _ViewEdges.end(); - } - - inline int viewedges_size() const - { - return _ViewEdges.size(); - } - - inline Vec2r getBeginningOrientation() const - { - return _extremityOrientations[0]; - } - - inline real getBeginningOrientationX() const - { - return _extremityOrientations[0].x(); - } - - inline real getBeginningOrientationY() const - { - return _extremityOrientations[0].y(); - } - - inline Vec2r getEndingOrientation() const - { - return _extremityOrientations[1]; - } - - inline real getEndingOrientationX() const - { - return _extremityOrientations[1].x(); - } - - inline real getEndingOrientationY() const - { - return _extremityOrientations[1].y(); - } - - - /* modifiers */ - /*! sets the Id of the Stroke. */ - inline void setId(const Id& id) - { - _id = id; - } - - /*! sets the 2D length of the Stroke. */ - void setLength(float iLength); - - /*! sets the medium type that must be used for this Stroke. */ - inline void setMediumType(MediumType iType) - { - _mediumType = iType; - } - - /*! sets the texture id to be used to simulate the marks system for this Stroke. */ - inline void setTextureId(unsigned int id) - { - _textureId = id; - } - - /*! sets the spacing of texture coordinates along the stroke lenght. */ - inline void setTextureStep(float step) - { - _textureStep = step; - } - - /*! assigns a blender texture to the first available slot. */ - inline int setMTex(MTex *mtex) - { - for (int a = 0; a < MAX_MTEX; a++) { - if (!_mtex[a]) { - _mtex[a] = mtex; - return 0; - } - } - return -1; /* no free slots */ - } - - /*! assigns a node tree (of new shading nodes) to define textures. */ - inline void setNodeTree(bNodeTree *iNodeTree) - { - _nodeTree = iNodeTree; - } - - /*! sets the flag telling whether this stroke is using a texture with tips or not. */ - inline void setTips(bool iTips) - { - _tips = iTips; - } - - inline void push_back(StrokeVertex *iVertex) - { - _Vertices.push_back(iVertex); - } - - inline void push_front(StrokeVertex *iVertex) - { - _Vertices.push_front(iVertex); - } - - inline void AddViewEdge(ViewEdge *iViewEdge) - { - _ViewEdges.push_back(iViewEdge); - } - - inline void setBeginningOrientation(const Vec2r& iOrientation) - { - _extremityOrientations[0] = iOrientation; - } - - inline void setBeginningOrientation(real x, real y) - { - _extremityOrientations[0] = Vec2r(x, y); - } - - inline void setEndingOrientation(const Vec2r& iOrientation) - { - _extremityOrientations[1] = iOrientation; - } - - inline void setEndingOrientation(real x, real y) - { - _extremityOrientations[1] = Vec2r(x, y); - } - - /* Information access interface */ - - // embedding vertex iterator - const_vertex_iterator vertices_begin() const; - vertex_iterator vertices_begin(float t = 0.0f); - const_vertex_iterator vertices_end() const; - vertex_iterator vertices_end(); - - /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the Stroke. One can specify a sampling - * value to resample the Stroke on the fly if needed. - * \param t: - * The resampling value with which we want our Stroke to be resampled. - * If 0 is specified, no resampling is done. - */ - StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t = 0.0f); - - /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the Stroke. */ - StrokeInternal::StrokeVertexIterator strokeVerticesEnd(); - - /*! Returns the number of StrokeVertex constituting the Stroke. */ - inline unsigned int strokeVerticesSize() const - { - return _Vertices.size(); - } - - /*! Returns the i-th StrokeVertex constituting the Stroke. */ - inline StrokeVertex& strokeVerticeAt(unsigned int i) - { - return *(_Vertices.at(i)); - } - - // Iterator access (Interface1D) - /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the Stroke. */ - virtual Interface0DIterator verticesBegin(); - - /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the Stroke. */ - virtual Interface0DIterator verticesEnd(); - - virtual Interface0DIterator pointsBegin(float t = 0.0f); - virtual Interface0DIterator pointsEnd(float t = 0.0f); +class Stroke : public Interface1D { + public: // Implementation of Interface1D + /*! Returns the string "Stroke" */ + virtual string getExactTypeName() const + { + return "Stroke"; + } + + // Data access methods + + /*! Returns the Id of the Stroke */ + virtual Id getId() const + { + return _id; + } + + /*! The different blending modes available to similate the interaction media-medium. */ + typedef enum { + DRY_MEDIUM, /*!< To simulate a dry medium such as Pencil or Charcoal.*/ + HUMID_MEDIUM, /*!< To simulate ink painting (color subtraction blending).*/ + OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/ + } MediumType; + + public: + typedef std::deque<StrokeVertex *> vertex_container; // the vertices container + typedef std::vector<ViewEdge *> viewedge_container; // the viewedges container + typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits> + vertex_iterator; + typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> + const_vertex_iterator; + + public: + //typedef StrokeVertex vertex_type; + + private: + vertex_container _Vertices; //! The stroke's backbone vertices + Id _id; + float _Length; // The stroke length + viewedge_container _ViewEdges; + float _sampling; + float _textureStep; + // StrokeRenderer *_renderer; // mark implementation OpenGL renderer + MediumType _mediumType; + unsigned int _textureId; + MTex *_mtex[MAX_MTEX]; + bNodeTree *_nodeTree; + bool _tips; + StrokeRep *_rep; + Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity + + public: + /*! default constructor */ + Stroke(); + + /*! copy constructor */ + Stroke(const Stroke &iBrother); + + /*! Builds a stroke from a set of StrokeVertex. + * This constructor is templated by an iterator type. + * This iterator type must allow the vertices parsing using the ++ operator. + * \param iBegin: + * The iterator pointing to the first vertex. + * \param iEnd: + * The iterator pointing to the end of the vertex list. + */ + template<class InputVertexIterator> Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd); + + /*! Destructor */ + virtual ~Stroke(); + + /* operators */ + /*! operator = */ + Stroke &operator=(const Stroke &iBrother); + + /*! Compute the sampling needed to get iNVertices vertices. + * If the specified number of vertices is less than the actual number of vertices, the actual sampling value + * is returned. (To remove Vertices, use the RemoveVertex() method of this class). + * \param iNVertices: + * The number of StrokeVertices we eventually want in our Stroke. + * \return the sampling that must be used in the Resample(float) method. + * \see Resample(int) + * \see Resample(float) + */ + float ComputeSampling(int iNVertices); + + /*! Resampling method. + * Resamples the curve so that it eventually has iNPoints. That means it is going to add iNPoints-vertices_size, + * if vertices_size is the number of points we already have. + * If vertices_size >= iNPoints, no resampling is done. + * \param iNPoints: + * The number of vertices we eventually want in our stroke. + */ + int Resample(int iNPoints); + + /*! Resampling method. + * Resamples the curve with a given sampling. + * If this sampling is < to the actual sampling value, no resampling is done. + * \param iSampling: + * The new sampling value. + */ + int Resample(float iSampling); + + /*! Removes all vertices from the Stroke. + */ + void RemoveAllVertices(); + + /*! Removes the stroke vertex iVertex + * from the stroke. + * The length and curvilinear abscissa are updated + * consequently. + */ + void RemoveVertex(StrokeVertex *iVertex); + + /*! Inserts the stroke vertex iVertex in the stroke before next. + * The length, curvilinear abscissa are updated consequently. + * \param iVertex: + * The StrokeVertex to insert in the Stroke. + * \param next: + * A StrokeVertexIterator pointing to the StrokeVeretx before which iVertex must be inserted. + */ + void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next); + + /*! Updates the 2D length of the Stroke */ + void UpdateLength(); + + /* Render method */ + void ScaleThickness(float iFactor); + void Render(const StrokeRenderer *iRenderer); + void RenderBasic(const StrokeRenderer *iRenderer); + + /* Iterator definition */ + + /* accessors */ + /*! Returns the 2D length of the Stroke */ + inline real getLength2D() const + { + return _Length; + } + + /*! Returns a reference to the time stamp value of the stroke. */ + /*! Returns the MediumType used for this Stroke. */ + inline MediumType getMediumType() const + { + return _mediumType; + } + + /*! Returns the id of the texture used to simulate th marks system for this Stroke */ + inline unsigned int getTextureId() + { + return _textureId; + } + + /*! Returns the spacing of texture coordinates along the stroke lenght */ + inline float getTextureStep() + { + return _textureStep; + } + + /*! Returns the texture used at given index to simulate the marks system for this Stroke */ + inline MTex *getMTex(int idx) + { + return _mtex[idx]; + } + + /*! Return the shader node tree to define textures. */ + inline bNodeTree *getNodeTree() + { + return _nodeTree; + } + + /*! Returns true if this Stroke has textures assigned, false otherwise. */ + inline bool hasTex() const + { + return (_mtex[0] != NULL) || _nodeTree; + } + + /*! Returns true if this Stroke uses a texture with tips, false otherwise. */ + inline bool hasTips() const + { + return _tips; + } + + /* these advanced iterators are used only in C++ */ + inline int vertices_size() const + { + return _Vertices.size(); + } + + inline viewedge_container::const_iterator viewedges_begin() const + { + return _ViewEdges.begin(); + } + + inline viewedge_container::iterator viewedges_begin() + { + return _ViewEdges.begin(); + } + + inline viewedge_container::const_iterator viewedges_end() const + { + return _ViewEdges.end(); + } + + inline viewedge_container::iterator viewedges_end() + { + return _ViewEdges.end(); + } + + inline int viewedges_size() const + { + return _ViewEdges.size(); + } + + inline Vec2r getBeginningOrientation() const + { + return _extremityOrientations[0]; + } + + inline real getBeginningOrientationX() const + { + return _extremityOrientations[0].x(); + } + + inline real getBeginningOrientationY() const + { + return _extremityOrientations[0].y(); + } + + inline Vec2r getEndingOrientation() const + { + return _extremityOrientations[1]; + } + + inline real getEndingOrientationX() const + { + return _extremityOrientations[1].x(); + } + + inline real getEndingOrientationY() const + { + return _extremityOrientations[1].y(); + } + + /* modifiers */ + /*! sets the Id of the Stroke. */ + inline void setId(const Id &id) + { + _id = id; + } + + /*! sets the 2D length of the Stroke. */ + void setLength(float iLength); + + /*! sets the medium type that must be used for this Stroke. */ + inline void setMediumType(MediumType iType) + { + _mediumType = iType; + } + + /*! sets the texture id to be used to simulate the marks system for this Stroke. */ + inline void setTextureId(unsigned int id) + { + _textureId = id; + } + + /*! sets the spacing of texture coordinates along the stroke lenght. */ + inline void setTextureStep(float step) + { + _textureStep = step; + } + + /*! assigns a blender texture to the first available slot. */ + inline int setMTex(MTex *mtex) + { + for (int a = 0; a < MAX_MTEX; a++) { + if (!_mtex[a]) { + _mtex[a] = mtex; + return 0; + } + } + return -1; /* no free slots */ + } + + /*! assigns a node tree (of new shading nodes) to define textures. */ + inline void setNodeTree(bNodeTree *iNodeTree) + { + _nodeTree = iNodeTree; + } + + /*! sets the flag telling whether this stroke is using a texture with tips or not. */ + inline void setTips(bool iTips) + { + _tips = iTips; + } + + inline void push_back(StrokeVertex *iVertex) + { + _Vertices.push_back(iVertex); + } + + inline void push_front(StrokeVertex *iVertex) + { + _Vertices.push_front(iVertex); + } + + inline void AddViewEdge(ViewEdge *iViewEdge) + { + _ViewEdges.push_back(iViewEdge); + } + + inline void setBeginningOrientation(const Vec2r &iOrientation) + { + _extremityOrientations[0] = iOrientation; + } + + inline void setBeginningOrientation(real x, real y) + { + _extremityOrientations[0] = Vec2r(x, y); + } + + inline void setEndingOrientation(const Vec2r &iOrientation) + { + _extremityOrientations[1] = iOrientation; + } + + inline void setEndingOrientation(real x, real y) + { + _extremityOrientations[1] = Vec2r(x, y); + } + + /* Information access interface */ + + // embedding vertex iterator + const_vertex_iterator vertices_begin() const; + vertex_iterator vertices_begin(float t = 0.0f); + const_vertex_iterator vertices_end() const; + vertex_iterator vertices_end(); + + /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the Stroke. One can specify a sampling + * value to resample the Stroke on the fly if needed. + * \param t: + * The resampling value with which we want our Stroke to be resampled. + * If 0 is specified, no resampling is done. + */ + StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t = 0.0f); + + /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the Stroke. */ + StrokeInternal::StrokeVertexIterator strokeVerticesEnd(); + + /*! Returns the number of StrokeVertex constituting the Stroke. */ + inline unsigned int strokeVerticesSize() const + { + return _Vertices.size(); + } + + /*! Returns the i-th StrokeVertex constituting the Stroke. */ + inline StrokeVertex &strokeVerticeAt(unsigned int i) + { + return *(_Vertices.at(i)); + } + + // Iterator access (Interface1D) + /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the Stroke. */ + virtual Interface0DIterator verticesBegin(); + + /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the Stroke. */ + virtual Interface0DIterator verticesEnd(); + + virtual Interface0DIterator pointsBegin(float t = 0.0f); + virtual Interface0DIterator pointsEnd(float t = 0.0f); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Stroke") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Stroke") #endif }; - // // Implementation // //////////////////////////////////////////////////////// - template<class InputVertexIterator> Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) { - for (InputVertexIterator v = iBegin, vend = iEnd; v != vend; v++) { - _Vertices.push_back(*v); - } - _Length = 0; - _id = 0; + for (InputVertexIterator v = iBegin, vend = iEnd; v != vend; v++) { + _Vertices.push_back(*v); + } + _Length = 0; + _id = 0; } } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_H__ +#endif // __FREESTYLE_STROKE_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h index 8362c293558..e9d4659f320 100644 --- a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h +++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h @@ -28,154 +28,155 @@ namespace Freestyle { namespace StrokeInternal { -class vertex_const_traits : public Const_traits<StrokeVertex*> -{ -public: - typedef std::deque<StrokeVertex*> vertex_container; - typedef vertex_container::const_iterator vertex_container_iterator; +class vertex_const_traits : public Const_traits<StrokeVertex *> { + public: + typedef std::deque<StrokeVertex *> vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator; }; -class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex*> -{ -public: - typedef std::deque<StrokeVertex*> vertex_container; //! the vertices container - typedef vertex_container::iterator vertex_container_iterator; +class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex *> { + public: + typedef std::deque<StrokeVertex *> vertex_container; //! the vertices container + typedef vertex_container::iterator vertex_container_iterator; }; - template<class Traits> -class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> -{ -public: - typedef vertex_iterator_base<Traits> Self; - -protected: - typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; - typedef typename Traits::vertex_container_iterator vertex_container_iterator; - typedef vertex_iterator_base<vertex_nonconst_traits> iterator; - typedef vertex_iterator_base<vertex_const_traits> const_iterator; - -//protected: -public: - vertex_container_iterator _it; - vertex_container_iterator _begin; - vertex_container_iterator _end; - -public: - friend class Stroke; - //friend class vertex_iterator; - - inline vertex_iterator_base() : parent_class() {} - - inline vertex_iterator_base(const iterator& iBrother) : parent_class() - { - _it = iBrother._it; - _begin = iBrother._begin; - _end = iBrother._end; - } - - inline vertex_iterator_base(const const_iterator& iBrother) : parent_class() - { - _it = iBrother._it; - _begin = iBrother._begin; - _end = iBrother._end; - } - -//protected: //FIXME -public: - inline vertex_iterator_base(vertex_container_iterator it, vertex_container_iterator begin, - vertex_container_iterator end) - : parent_class() - { - _it = it; - _begin = begin; - _end = end; - } - -public: - virtual ~vertex_iterator_base() {} - - virtual bool begin() const - { - return (_it == _begin) ? true : false; - } - - virtual bool end() const - { - return (_it == _end) ? true : false; - } - - // operators - inline Self& operator++() // operator corresponding to ++i - { - ++_it; - return *(this); - } - - /* Operator corresponding to i++, i.e. which returns the value *and then* increments. - * That's why we store the value in a temp. - */ - inline Self operator++(int) - { - Self tmp = *this; - ++_it; - return tmp; - } - - inline Self& operator--() // operator corresponding to --i - { - --_it; - return *(this); - } - - inline Self operator--(int) - { - Self tmp = *this; - --_it; - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - return (_it != b._it); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual typename Traits::reference operator*() const - { - return *(_it); - } - - virtual typename Traits::pointer operator->() const - { - return &(operator*()); - } - - /*! accessors */ - inline vertex_container_iterator it() const - { - return _it; - } - - inline vertex_container_iterator getBegin() const - { - return _begin; - } - - inline vertex_container_iterator getEnd() const - { - return _end; - } +class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> { + public: + typedef vertex_iterator_base<Traits> Self; + + protected: + typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; + typedef typename Traits::vertex_container_iterator vertex_container_iterator; + typedef vertex_iterator_base<vertex_nonconst_traits> iterator; + typedef vertex_iterator_base<vertex_const_traits> const_iterator; + + //protected: + public: + vertex_container_iterator _it; + vertex_container_iterator _begin; + vertex_container_iterator _end; + + public: + friend class Stroke; + //friend class vertex_iterator; + + inline vertex_iterator_base() : parent_class() + { + } + + inline vertex_iterator_base(const iterator &iBrother) : parent_class() + { + _it = iBrother._it; + _begin = iBrother._begin; + _end = iBrother._end; + } + + inline vertex_iterator_base(const const_iterator &iBrother) : parent_class() + { + _it = iBrother._it; + _begin = iBrother._begin; + _end = iBrother._end; + } + + //protected: //FIXME + public: + inline vertex_iterator_base(vertex_container_iterator it, + vertex_container_iterator begin, + vertex_container_iterator end) + : parent_class() + { + _it = it; + _begin = begin; + _end = end; + } + + public: + virtual ~vertex_iterator_base() + { + } + + virtual bool begin() const + { + return (_it == _begin) ? true : false; + } + + virtual bool end() const + { + return (_it == _end) ? true : false; + } + + // operators + inline Self &operator++() // operator corresponding to ++i + { + ++_it; + return *(this); + } + + /* Operator corresponding to i++, i.e. which returns the value *and then* increments. + * That's why we store the value in a temp. + */ + inline Self operator++(int) + { + Self tmp = *this; + ++_it; + return tmp; + } + + inline Self &operator--() // operator corresponding to --i + { + --_it; + return *(this); + } + + inline Self operator--(int) + { + Self tmp = *this; + --_it; + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + return (_it != b._it); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual typename Traits::reference operator*() const + { + return *(_it); + } + + virtual typename Traits::pointer operator->() const + { + return &(operator*()); + } + + /*! accessors */ + inline vertex_container_iterator it() const + { + return _it; + } + + inline vertex_container_iterator getBegin() const + { + return _begin; + } + + inline vertex_container_iterator getEnd() const + { + return _end; + } }; -} // end of namespace StrokeInternal +} // end of namespace StrokeInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__ +#endif // __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.cpp b/source/blender/freestyle/intern/stroke/StrokeIO.cpp index 9b428a81d1e..686313cd04e 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIO.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp @@ -25,44 +25,43 @@ namespace Freestyle { -ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute) +ostream &operator<<(ostream &out, const StrokeAttribute &iStrokeAttribute) { - out << " StrokeAttribute" << endl; - out << " color : (" << iStrokeAttribute.getColorR() << "," << iStrokeAttribute.getColorG() << - "," << iStrokeAttribute.getColorB() << ")" << endl; - out << " alpha : " << iStrokeAttribute.getAlpha() << endl; - out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " << iStrokeAttribute.getThicknessL() << - endl; - out << " visible : " << iStrokeAttribute.isVisible() << endl; - return out; + out << " StrokeAttribute" << endl; + out << " color : (" << iStrokeAttribute.getColorR() << "," + << iStrokeAttribute.getColorG() << "," << iStrokeAttribute.getColorB() << ")" << endl; + out << " alpha : " << iStrokeAttribute.getAlpha() << endl; + out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " + << iStrokeAttribute.getThicknessL() << endl; + out << " visible : " << iStrokeAttribute.isVisible() << endl; + return out; } -ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex) +ostream &operator<<(ostream &out, const StrokeVertex &iStrokeVertex) { - out << " StrokeVertex" << endl; - out << " id : " << iStrokeVertex.getId() << endl; - out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl; - out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," << iStrokeVertex.getProjectedY() << - "," << iStrokeVertex.getProjectedZ() << ")" << endl; - out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() << - "," << iStrokeVertex.getZ() << ")" << endl; - out << iStrokeVertex.attribute() << endl; - return out; + out << " StrokeVertex" << endl; + out << " id : " << iStrokeVertex.getId() << endl; + out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl; + out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," + << iStrokeVertex.getProjectedY() << "," << iStrokeVertex.getProjectedZ() << ")" << endl; + out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() << "," + << iStrokeVertex.getZ() << ")" << endl; + out << iStrokeVertex.attribute() << endl; + return out; } -ostream& operator<<(ostream& out, const Stroke& iStroke) +ostream &operator<<(ostream &out, const Stroke &iStroke) { - out << "Stroke" << endl; - out << " id : " << iStroke.getId() << endl; - out << " length : " << iStroke.getLength2D() << endl; - out << " medium type : " << iStroke.getMediumType() << endl; - for (Stroke::const_vertex_iterator v = iStroke.vertices_begin(), vend = iStroke.vertices_end(); - v != vend; - ++v) - { - out << *(*v) << endl; - } - return out; + out << "Stroke" << endl; + out << " id : " << iStroke.getId() << endl; + out << " length : " << iStroke.getLength2D() << endl; + out << " medium type : " << iStroke.getMediumType() << endl; + for (Stroke::const_vertex_iterator v = iStroke.vertices_begin(), vend = iStroke.vertices_end(); + v != vend; + ++v) { + out << *(*v) << endl; + } + return out; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h index 7ce5091e9fe..ae38847f8cc 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIO.h +++ b/source/blender/freestyle/intern/stroke/StrokeIO.h @@ -30,12 +30,12 @@ namespace Freestyle { -ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute); +ostream &operator<<(ostream &out, const StrokeAttribute &iStrokeAttribute); -ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex); +ostream &operator<<(ostream &out, const StrokeVertex &iStrokeVertex); -ostream& operator<<(ostream& out, const Stroke& iStroke); +ostream &operator<<(ostream &out, const Stroke &iStroke); } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_IO_H__ +#endif // __FREESTYLE_STROKE_IO_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h index d64fbdfd83c..1999b028424 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIterators.h +++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h @@ -46,187 +46,190 @@ namespace StrokeInternal { * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 StrokeVertexIterator. * Otherwise, incrementing \a it1 will also increment \a it2. */ -class StrokeVertexIterator : public Interface0DIteratorNested -{ -public: - /*! Default constructor. */ - StrokeVertexIterator() {} - - /*! Copy constructor. */ - StrokeVertexIterator(const StrokeVertexIterator& vi) - { - _it = vi._it; - _begin = vi._begin; - _end = vi._end; - } - - StrokeVertexIterator(const Stroke::vertex_container::iterator& it, - const Stroke::vertex_container::iterator& begin, - const Stroke::vertex_container::iterator& end) - { - _it = it; - _begin = begin; - _end = end; - } - - virtual ~StrokeVertexIterator() {} - - /*! Casts this StrokeVertexIterator into an Interface0DIterator. - * Useful for any call to a function of the type UnaryFunction0D. - */ - inline Interface0DIterator castToInterface0DIterator() const - { - Interface0DIterator ret(new StrokeVertexIterator(*this)); - return ret; - } - - /*! operator= - * \attention In the scripting language, you must call \code it2 = StrokeVertexIterator(it1) \endcode instead of - * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 StrokeVertexIterator. - * Otherwise, incrementing \a it1 will also increment \a it2. - */ - StrokeVertexIterator& operator=(const StrokeVertexIterator& vi) - { - _it = vi._it; - _begin = vi._begin; - _end = vi._end; - return *this; - } - - /*! Returns the string "StrokeVertexIterator". */ - virtual string getExactTypeName() const - { - return "StrokeVertexIterator"; - } - - /*! Returns a reference to the pointed StrokeVertex. - * In the scripting language, you must call "getObject()"instead. - */ - virtual StrokeVertex& operator*() - { - return **_it; - } - - /*! Returns a pointer to the pointed StrokeVertex. - * Can't be called in the scripting language. - */ - virtual StrokeVertex *operator->() - { - return &(operator*()); - } - - /*! Increments. In the scripting language, call "increment()". */ - virtual StrokeVertexIterator& operator++() - { - increment(); - return *this; - } - - /*! Increments. In the scripting language, call "increment()". */ - virtual StrokeVertexIterator operator++(int) - { - StrokeVertexIterator ret(*this); - increment(); - return ret; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - virtual StrokeVertexIterator& operator--() - { - decrement(); - return *this; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - virtual StrokeVertexIterator operator--(int) - { - StrokeVertexIterator ret(*this); - decrement(); - return ret; - } - - /*! Increments. */ - virtual int increment() - { - ++_it; - return 0; - } - - /*! Decrements. */ - virtual int decrement() - { - --_it; - return 0; - } - - /*! Returns true if the pointed StrokeVertex is the first of the Stroke. */ - bool isBegin() const - { - return _it == _begin; - } - - /*! Returns true if the pointed StrokeVertex is the final valid StrokeVertex of the Stroke. */ - bool atLast() - { - if (_it == _end) - return false; - - ++_it; - bool result = (_it == _end); - --_it; - return result; - } - - /*! Returns true if the pointed StrokeVertex is after the last StrokeVertex of the Stroke. */ - bool isEnd() const - { - return _it == _end; - } - - /*! operator == */ - virtual bool operator==(const Interface0DIteratorNested& it) const - { - const StrokeVertexIterator *it_exact = dynamic_cast<const StrokeVertexIterator *>(&it); - if (!it_exact) - return false; - return (_it == it_exact->_it); - } - - /*! Returns the curvilinear abscissa of the current point */ - virtual float t() const - { - return (*_it)->curvilinearAbscissa(); - } - - /*! Returns the point's parameter in the stroke */ - virtual float u() const - { - return (*_it)->u(); - } - - /*! Cloning method */ - virtual StrokeVertexIterator *copy() const - { - return new StrokeVertexIterator(*this); - } - - // - // Not exported in Python - // - ////////////////////////////////////////////////// - const Stroke::vertex_container::iterator& getIt() - { - return _it; - } - -private: - Stroke::vertex_container::iterator _it; - Stroke::vertex_container::iterator _begin; - Stroke::vertex_container::iterator _end; +class StrokeVertexIterator : public Interface0DIteratorNested { + public: + /*! Default constructor. */ + StrokeVertexIterator() + { + } + + /*! Copy constructor. */ + StrokeVertexIterator(const StrokeVertexIterator &vi) + { + _it = vi._it; + _begin = vi._begin; + _end = vi._end; + } + + StrokeVertexIterator(const Stroke::vertex_container::iterator &it, + const Stroke::vertex_container::iterator &begin, + const Stroke::vertex_container::iterator &end) + { + _it = it; + _begin = begin; + _end = end; + } + + virtual ~StrokeVertexIterator() + { + } + + /*! Casts this StrokeVertexIterator into an Interface0DIterator. + * Useful for any call to a function of the type UnaryFunction0D. + */ + inline Interface0DIterator castToInterface0DIterator() const + { + Interface0DIterator ret(new StrokeVertexIterator(*this)); + return ret; + } + + /*! operator= + * \attention In the scripting language, you must call \code it2 = StrokeVertexIterator(it1) \endcode instead of + * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 StrokeVertexIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + */ + StrokeVertexIterator &operator=(const StrokeVertexIterator &vi) + { + _it = vi._it; + _begin = vi._begin; + _end = vi._end; + return *this; + } + + /*! Returns the string "StrokeVertexIterator". */ + virtual string getExactTypeName() const + { + return "StrokeVertexIterator"; + } + + /*! Returns a reference to the pointed StrokeVertex. + * In the scripting language, you must call "getObject()"instead. + */ + virtual StrokeVertex &operator*() + { + return **_it; + } + + /*! Returns a pointer to the pointed StrokeVertex. + * Can't be called in the scripting language. + */ + virtual StrokeVertex *operator->() + { + return &(operator*()); + } + + /*! Increments. In the scripting language, call "increment()". */ + virtual StrokeVertexIterator &operator++() + { + increment(); + return *this; + } + + /*! Increments. In the scripting language, call "increment()". */ + virtual StrokeVertexIterator operator++(int) + { + StrokeVertexIterator ret(*this); + increment(); + return ret; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + virtual StrokeVertexIterator &operator--() + { + decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + virtual StrokeVertexIterator operator--(int) + { + StrokeVertexIterator ret(*this); + decrement(); + return ret; + } + + /*! Increments. */ + virtual int increment() + { + ++_it; + return 0; + } + + /*! Decrements. */ + virtual int decrement() + { + --_it; + return 0; + } + + /*! Returns true if the pointed StrokeVertex is the first of the Stroke. */ + bool isBegin() const + { + return _it == _begin; + } + + /*! Returns true if the pointed StrokeVertex is the final valid StrokeVertex of the Stroke. */ + bool atLast() + { + if (_it == _end) + return false; + + ++_it; + bool result = (_it == _end); + --_it; + return result; + } + + /*! Returns true if the pointed StrokeVertex is after the last StrokeVertex of the Stroke. */ + bool isEnd() const + { + return _it == _end; + } + + /*! operator == */ + virtual bool operator==(const Interface0DIteratorNested &it) const + { + const StrokeVertexIterator *it_exact = dynamic_cast<const StrokeVertexIterator *>(&it); + if (!it_exact) + return false; + return (_it == it_exact->_it); + } + + /*! Returns the curvilinear abscissa of the current point */ + virtual float t() const + { + return (*_it)->curvilinearAbscissa(); + } + + /*! Returns the point's parameter in the stroke */ + virtual float u() const + { + return (*_it)->u(); + } + + /*! Cloning method */ + virtual StrokeVertexIterator *copy() const + { + return new StrokeVertexIterator(*this); + } + + // + // Not exported in Python + // + ////////////////////////////////////////////////// + const Stroke::vertex_container::iterator &getIt() + { + return _it; + } + + private: + Stroke::vertex_container::iterator _it; + Stroke::vertex_container::iterator _begin; + Stroke::vertex_container::iterator _end; }; -} // end of namespace StrokeInternal +} // end of namespace StrokeInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_ITERATORS_H__ +#endif // __FREESTYLE_STROKE_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp index 3976c56ffe2..f1680279889 100644 --- a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp @@ -27,35 +27,41 @@ namespace Freestyle { StrokeLayer::~StrokeLayer() { - clear(); + clear(); } void StrokeLayer::ScaleThickness(float iFactor) { - for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) { - (*s)->ScaleThickness(iFactor); - } + for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); + s != send; + ++s) { + (*s)->ScaleThickness(iFactor); + } } void StrokeLayer::Render(const StrokeRenderer *iRenderer) { - for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) { - (*s)->Render(iRenderer); - } + for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); + s != send; + ++s) { + (*s)->Render(iRenderer); + } } void StrokeLayer::RenderBasic(const StrokeRenderer *iRenderer) { - for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) { - (*s)->RenderBasic(iRenderer); - } + for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); + s != send; + ++s) { + (*s)->RenderBasic(iRenderer); + } } void StrokeLayer::clear() { - for (stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) - delete *s; - _strokes.clear(); + for (stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) + delete *s; + _strokes.clear(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h index 1eef44e6c91..ecb98025875 100644 --- a/source/blender/freestyle/intern/stroke/StrokeLayer.h +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h @@ -25,81 +25,82 @@ #include <deque> #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { class Stroke; class StrokeRenderer; -class StrokeLayer -{ -public: - typedef std::deque<Stroke*> stroke_container; - -protected: - stroke_container _strokes; - -public: - StrokeLayer() {} - - StrokeLayer(const stroke_container& iStrokes) - { - _strokes = iStrokes; - } - - StrokeLayer(const StrokeLayer& iBrother) - { - _strokes = iBrother._strokes; - } - - virtual ~StrokeLayer(); - - /*! Render method */ - void ScaleThickness(float iFactor); - void Render(const StrokeRenderer *iRenderer); - void RenderBasic(const StrokeRenderer *iRenderer); - - /*! clears the layer */ - void clear(); - - /*! accessors */ - inline stroke_container::iterator strokes_begin() - { - return _strokes.begin(); - } - - inline stroke_container::iterator strokes_end() - { - return _strokes.end(); - } - - inline int strokes_size() const - { - return _strokes.size(); - } - - inline bool empty() const - { - return _strokes.empty(); - } - - /*! modifiers */ - inline void setStrokes(stroke_container& iStrokes) - { - _strokes = iStrokes; - } - - inline void AddStroke(Stroke *iStroke) - { - _strokes.push_back(iStroke); - } +class StrokeLayer { + public: + typedef std::deque<Stroke *> stroke_container; + + protected: + stroke_container _strokes; + + public: + StrokeLayer() + { + } + + StrokeLayer(const stroke_container &iStrokes) + { + _strokes = iStrokes; + } + + StrokeLayer(const StrokeLayer &iBrother) + { + _strokes = iBrother._strokes; + } + + virtual ~StrokeLayer(); + + /*! Render method */ + void ScaleThickness(float iFactor); + void Render(const StrokeRenderer *iRenderer); + void RenderBasic(const StrokeRenderer *iRenderer); + + /*! clears the layer */ + void clear(); + + /*! accessors */ + inline stroke_container::iterator strokes_begin() + { + return _strokes.begin(); + } + + inline stroke_container::iterator strokes_end() + { + return _strokes.end(); + } + + inline int strokes_size() const + { + return _strokes.size(); + } + + inline bool empty() const + { + return _strokes.empty(); + } + + /*! modifiers */ + inline void setStrokes(stroke_container &iStrokes) + { + _strokes = iStrokes; + } + + inline void AddStroke(Stroke *iStroke) + { + _strokes.push_back(iStroke); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeLayer") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeLayer") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_LAYER_H__ +#endif // __FREESTYLE_STROKE_LAYER_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp index 303b6c67984..530a7644bfa 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp @@ -37,17 +37,20 @@ namespace Freestyle { TextureManager *StrokeRenderer::_textureManager = 0; -StrokeRenderer::StrokeRenderer() {} +StrokeRenderer::StrokeRenderer() +{ +} -StrokeRenderer::~StrokeRenderer() {} +StrokeRenderer::~StrokeRenderer() +{ +} bool StrokeRenderer::loadTextures() { - _textureManager->load(); - return true; + _textureManager->load(); + return true; } - /**********************************/ /* */ /* */ @@ -56,7 +59,6 @@ bool StrokeRenderer::loadTextures() /* */ /**********************************/ - TextureManager *TextureManager::_pInstance = 0; string TextureManager::_patterns_path; @@ -65,61 +67,61 @@ string TextureManager::_brushes_path; TextureManager::TextureManager() { - _hasLoadedTextures = false; - _pInstance = this; - _defaultTextureId = 0; + _hasLoadedTextures = false; + _pInstance = this; + _defaultTextureId = 0; } TextureManager::~TextureManager() { - if (!_brushesMap.empty()) - _brushesMap.clear(); - _pInstance = 0; + if (!_brushesMap.empty()) + _brushesMap.clear(); + _pInstance = 0; } void TextureManager::load() { - if (_hasLoadedTextures) - return; - loadStandardBrushes(); - _hasLoadedTextures = true; + if (_hasLoadedTextures) + return; + loadStandardBrushes(); + _hasLoadedTextures = true; } unsigned TextureManager::getBrushTextureIndex(string name, Stroke::MediumType loadingMode) { - BrushTexture bt(name, loadingMode); - brushesMap::iterator b = _brushesMap.find(bt); - if (b == _brushesMap.end()) { - unsigned texId = loadBrush(name, loadingMode); - _brushesMap[bt] = texId; - return texId; - // XXX! - cerr << "brush file " << name << " not found" << endl; - return 0; - } - else { - return _brushesMap[bt]; - } + BrushTexture bt(name, loadingMode); + brushesMap::iterator b = _brushesMap.find(bt); + if (b == _brushesMap.end()) { + unsigned texId = loadBrush(name, loadingMode); + _brushesMap[bt] = texId; + return texId; + // XXX! + cerr << "brush file " << name << " not found" << endl; + return 0; + } + else { + return _brushesMap[bt]; + } } -void TextureManager::Options::setPatternsPath(const string& path) +void TextureManager::Options::setPatternsPath(const string &path) { - _patterns_path = path; + _patterns_path = path; } string TextureManager::Options::getPatternsPath() { - return _patterns_path; + return _patterns_path; } -void TextureManager::Options::setBrushesPath(const string& path) +void TextureManager::Options::setBrushesPath(const string &path) { - _brushes_path = path; + _brushes_path = path; } string TextureManager::Options::getBrushesPath() { - return _brushes_path; + return _brushes_path; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h index 35e206a73c0..03e6893b578 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h @@ -34,7 +34,7 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -47,72 +47,67 @@ namespace Freestyle { /* */ /**********************************/ - /*! Class to load textures */ -class TextureManager -{ -public: - TextureManager (); - virtual ~TextureManager (); - - static TextureManager *getInstance() - { - return _pInstance; - } - - void load(); - unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM); - - inline bool hasLoaded() const - { - return _hasLoadedTextures; - } - - inline unsigned int getDefaultTextureId() const - { - return _defaultTextureId; - } - - struct Options - { - static void setPatternsPath(const string& path); - static string getPatternsPath(); - - static void setBrushesPath(const string& path); - static string getBrushesPath(); - }; - -protected: - virtual void loadStandardBrushes() = 0; - virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0; - - typedef std::pair<string, Stroke::MediumType> BrushTexture; - struct cmpBrushTexture - { - bool operator()(const BrushTexture& bt1, const BrushTexture& bt2) const - { - int r = strcmp(bt1.first.c_str(), bt2.first.c_str()); - if (r != 0) - return (r < 0); - else - return (bt1.second < bt2.second); - } - }; - typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap; - - static TextureManager *_pInstance; - bool _hasLoadedTextures; - brushesMap _brushesMap; - static string _patterns_path; - static string _brushes_path; - unsigned int _defaultTextureId; +class TextureManager { + public: + TextureManager(); + virtual ~TextureManager(); + + static TextureManager *getInstance() + { + return _pInstance; + } + + void load(); + unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM); + + inline bool hasLoaded() const + { + return _hasLoadedTextures; + } + + inline unsigned int getDefaultTextureId() const + { + return _defaultTextureId; + } + + struct Options { + static void setPatternsPath(const string &path); + static string getPatternsPath(); + + static void setBrushesPath(const string &path); + static string getBrushesPath(); + }; + + protected: + virtual void loadStandardBrushes() = 0; + virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0; + + typedef std::pair<string, Stroke::MediumType> BrushTexture; + struct cmpBrushTexture { + bool operator()(const BrushTexture &bt1, const BrushTexture &bt2) const + { + int r = strcmp(bt1.first.c_str(), bt2.first.c_str()); + if (r != 0) + return (r < 0); + else + return (bt1.second < bt2.second); + } + }; + typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap; + + static TextureManager *_pInstance; + bool _hasLoadedTextures; + brushesMap _brushesMap; + static string _patterns_path; + static string _brushes_path; + unsigned int _defaultTextureId; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TextureManager") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TextureManager") #endif }; - /**********************************/ /* */ /* */ @@ -122,28 +117,27 @@ protected: /**********************************/ /*! Class to render a stroke. Creates a triangle strip and stores it strip is lazily created at the first rendering */ -class StrokeRenderer -{ -public: - StrokeRenderer(); - virtual ~StrokeRenderer(); +class StrokeRenderer { + public: + StrokeRenderer(); + virtual ~StrokeRenderer(); - /*! Renders a stroke rep */ - virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0; - virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0; + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0; - // initializes the texture manager - // lazy, checks if it has already been done - static bool loadTextures(); + // initializes the texture manager + // lazy, checks if it has already been done + static bool loadTextures(); - //static unsigned int getTextureIndex(unsigned int index); - static TextureManager *_textureManager; + //static unsigned int getTextureIndex(unsigned int index); + static TextureManager *_textureManager; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeRenderer") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeRenderer") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_RENDERER_H__ +#endif // __FREESTYLE_STROKE_RENDERER_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp index 9a593c93b08..026a7b2fc8f 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp @@ -35,53 +35,58 @@ namespace Freestyle { // STROKE VERTEX REP ///////////////////////////////////// -StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother) +StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep &iBrother) { - _point2d = iBrother._point2d; - _texCoord = iBrother._texCoord; - _texCoord_w_tips = iBrother._texCoord_w_tips; - _color = iBrother._color; - _alpha = iBrother._alpha; + _point2d = iBrother._point2d; + _texCoord = iBrother._texCoord; + _texCoord_w_tips = iBrother._texCoord_w_tips; + _color = iBrother._color; + _alpha = iBrother._alpha; } // // STRIP ///////////////////////////////////// -Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTex, bool beginTip, bool endTip, float texStep) +Strip::Strip(const vector<StrokeVertex *> &iStrokeVertices, + bool hasTex, + bool beginTip, + bool endTip, + float texStep) { - createStrip(iStrokeVertices); + createStrip(iStrokeVertices); - setVertexColor(iStrokeVertices); + setVertexColor(iStrokeVertices); - if (hasTex) { - // We compute both kinds of coordinates to use different kinds of textures - computeTexCoord(iStrokeVertices, texStep); - computeTexCoordWithTips(iStrokeVertices, beginTip, endTip, texStep); - } + if (hasTex) { + // We compute both kinds of coordinates to use different kinds of textures + computeTexCoord(iStrokeVertices, texStep); + computeTexCoordWithTips(iStrokeVertices, beginTip, endTip, texStep); + } } -Strip::Strip(const Strip& iBrother) +Strip::Strip(const Strip &iBrother) { - if (!iBrother._vertices.empty()) { - for (vertex_container::const_iterator v = iBrother._vertices.begin(), vend = iBrother._vertices.end(); - v != vend; - ++v) - { - _vertices.push_back(new StrokeVertexRep(**v)); - } - } - _averageThickness = iBrother._averageThickness; + if (!iBrother._vertices.empty()) { + for (vertex_container::const_iterator v = iBrother._vertices.begin(), + vend = iBrother._vertices.end(); + v != vend; + ++v) { + _vertices.push_back(new StrokeVertexRep(**v)); + } + } + _averageThickness = iBrother._averageThickness; } Strip::~Strip() { - if (!_vertices.empty()) { - for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) { - delete (*v); - } - _vertices.clear(); - } + if (!_vertices.empty()) { + for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; + ++v) { + delete (*v); + } + _vertices.clear(); + } } ////////////////////////// @@ -93,594 +98,605 @@ Strip::~Strip() #define MAX_RATIO_LENGTH_SINGU 2 #define HUGE_COORD 1.0e4 -static bool notValid (Vec2r p) +static bool notValid(Vec2r p) { - return (p[0] != p[0]) || (p[1] != p[1]) || (fabs(p[0]) > HUGE_COORD) || (fabs(p[1]) > HUGE_COORD) || - (p[0] < -HUGE_COORD) || (p[1] < -HUGE_COORD); + return (p[0] != p[0]) || (p[1] != p[1]) || (fabs(p[0]) > HUGE_COORD) || + (fabs(p[1]) > HUGE_COORD) || (p[0] < -HUGE_COORD) || (p[1] < -HUGE_COORD); } #if 0 static real crossP(const Vec2r& A, const Vec2r& B) { - return A[0] * B[1] - A[1] * B[0]; + return A[0] * B[1] - A[1] * B[0]; } #endif -void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) +void Strip::createStrip(const vector<StrokeVertex *> &iStrokeVertices) { - //computeParameterization(); - if (iStrokeVertices.size() < 2) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: strip has less than 2 vertices" << endl; - } - return; - } - _vertices.reserve(2 * iStrokeVertices.size()); - if (!_vertices.empty()) { - for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) { - delete (*v); - } - _vertices.clear(); - } - _averageThickness = 0.0; - - vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev; - StrokeVertex *sv, *sv2, *svPrev; - int orientationErrors = 0; - - //special case of first vertex - v2 = v = iStrokeVertices.begin(); - ++v2; - sv = *v; - vPrev = v; //in case the stroke has only 2 vertices; - sv2 = *v2; - Vec2r dir(sv2->getPoint() - sv->getPoint()); - Vec2r orthDir(-dir[1], dir[0]); - if (orthDir.norm() > ZERO) - orthDir.normalize(); - Vec2r stripDir(orthDir); - // check whether the orientation was user defined - if (sv->attribute().isAttributeAvailableVec2f("orientation")) { - Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); - if (userDir.norm() > 1e-6) { - userDir.normalize(); - real dp = userDir * orthDir; - if (dp < 0) - userDir = userDir * (-1.0f); - stripDir = userDir; - } - else { - ++orientationErrors; - } - } - const float *thickness = sv->attribute().getThickness(); - _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thickness[1] * stripDir)); - _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thickness[0] * stripDir)); + //computeParameterization(); + if (iStrokeVertices.size() < 2) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: strip has less than 2 vertices" << endl; + } + return; + } + _vertices.reserve(2 * iStrokeVertices.size()); + if (!_vertices.empty()) { + for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; + ++v) { + delete (*v); + } + _vertices.clear(); + } + _averageThickness = 0.0; + + vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev; + StrokeVertex *sv, *sv2, *svPrev; + int orientationErrors = 0; + + //special case of first vertex + v2 = v = iStrokeVertices.begin(); + ++v2; + sv = *v; + vPrev = v; //in case the stroke has only 2 vertices; + sv2 = *v2; + Vec2r dir(sv2->getPoint() - sv->getPoint()); + Vec2r orthDir(-dir[1], dir[0]); + if (orthDir.norm() > ZERO) + orthDir.normalize(); + Vec2r stripDir(orthDir); + // check whether the orientation was user defined + if (sv->attribute().isAttributeAvailableVec2f("orientation")) { + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + if (userDir.norm() > 1e-6) { + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDir = userDir; + } + else { + ++orientationErrors; + } + } + const float *thickness = sv->attribute().getThickness(); + _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thickness[1] * stripDir)); + _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thickness[0] * stripDir)); #if 0 - Vec2r userDir = _stroke->getBeginningOrientation(); - if (userDir != Vec2r(0, 0)) { - userDir.normalize(); - real o1 = (orthDir * userDir); - real o2 = crossP(orthDir, userDir); - real orientation = o1 * o2; - if (orientation > 0) { - // then the vertex to move is v0 - if (o1 > 0) - _vertex[0] = _vertex[1] + userDir; - else - _vertex[0] = _vertex[1] - userDir; - } - if (orientation < 0) { - // then we must move v1 - if (o1 < 0) - _vertex[1] = _vertex[0] + userDir; - else - _vertex[1] = _vertex[0] - userDir; - } - } + Vec2r userDir = _stroke->getBeginningOrientation(); + if (userDir != Vec2r(0, 0)) { + userDir.normalize(); + real o1 = (orthDir * userDir); + real o2 = crossP(orthDir, userDir); + real orientation = o1 * o2; + if (orientation > 0) { + // then the vertex to move is v0 + if (o1 > 0) + _vertex[0] = _vertex[1] + userDir; + else + _vertex[0] = _vertex[1] - userDir; + } + if (orientation < 0) { + // then we must move v1 + if (o1 < 0) + _vertex[1] = _vertex[0] + userDir; + else + _vertex[1] = _vertex[0] - userDir; + } + } #endif - int i = 2; // 2 because we have already processed the first vertex - - for (vend = iStrokeVertices.end(), ++v, ++v2; v2 != vend; vPrev = v++, ++v2) { - sv = (*v); - sv2 = (*v2); - svPrev = (*vPrev); - Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint()); - - //direction and orthogonal vector to the next segment - Vec2r dir(p2 - p); - float dirNorm = dir.norm(); - dir.normalize(); - Vec2r orthDir(-dir[1], dir[0]); - Vec2r stripDir = orthDir; - if (sv->attribute().isAttributeAvailableVec2f("orientation")) { - Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); - if (userDir.norm() > 1e-6) { - userDir.normalize(); - real dp = userDir * orthDir; - if (dp < 0) - userDir = userDir * (-1.0f); - stripDir = userDir; - } - else { - ++orientationErrors; - } - } - - //direction and orthogonal vector to the previous segment - Vec2r dirPrev(p - pPrev); - float dirPrevNorm = dirPrev.norm(); - dirPrev.normalize(); - Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]); - Vec2r stripDirPrev = orthDirPrev; - if (svPrev->attribute().isAttributeAvailableVec2f("orientation")) { - Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation"); - if (userDir.norm() > 1e-6) { - userDir.normalize(); - real dp = userDir * orthDir; - if (dp < 0) - userDir = userDir * (-1.0f); - stripDirPrev = userDir; - } - else { - ++orientationErrors; - } - } - - const float *thickness = sv->attribute().getThickness(); - _averageThickness += thickness[0] + thickness[1]; - Vec2r pInter; - int interResult; - - interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev + thickness[1] * stripDirPrev), - Vec2r(p + thickness[1] * stripDirPrev), - Vec2r(p + thickness[1] * stripDir), - Vec2r(p2 + thickness[1] * stripDir), - pInter); - if (interResult == GeomUtils::DO_INTERSECT) - _vertices.push_back(new StrokeVertexRep(pInter)); - else - _vertices.push_back(new StrokeVertexRep(p + thickness[1] * stripDir)); - ++i; - - interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev - thickness[0] * stripDirPrev), - Vec2r(p - thickness[0] * stripDirPrev), - Vec2r(p - thickness[0] * stripDir), - Vec2r(p2 - thickness[0] * stripDir), - pInter); - if (interResult == GeomUtils::DO_INTERSECT) - _vertices.push_back(new StrokeVertexRep(pInter)); - else - _vertices.push_back(new StrokeVertexRep(p - thickness[0] * stripDir)); - ++i; - - // if the angle is obtuse, we simply average the directions to avoid the singularity - stripDir = stripDir + stripDirPrev; - if ((dirNorm < ZERO) || (dirPrevNorm < ZERO) || (stripDir.norm() < ZERO)) { - stripDir[0] = 0; - stripDir[1] = 0; - } - else { - stripDir.normalize(); - } - - Vec2r vec_tmp(_vertices[i - 2]->point2d() - p); - if ((vec_tmp.norm() > thickness[1] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) || - notValid(_vertices[i - 2]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER)) - { - _vertices[i - 2]->setPoint2d(p + thickness[1] * stripDir); - } - - vec_tmp = _vertices[i - 1]->point2d() - p; - if ((vec_tmp.norm() > thickness[0] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) || - notValid(_vertices[i - 1]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER)) - { - _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir); - } - } // end of for - - //special case of last vertex - sv = *v; - sv2 = *vPrev; - dir = Vec2r(sv->getPoint() - sv2->getPoint()); - orthDir = Vec2r(-dir[1], dir[0]); - if (orthDir.norm() > ZERO) - orthDir.normalize(); - Vec2r stripDirLast(orthDir); - // check whether the orientation was user defined - if (sv->attribute().isAttributeAvailableVec2f("orientation")) { - Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); - if (userDir.norm() > 1e-6) { - userDir.normalize(); - real dp = userDir * orthDir; - if (dp < 0) - userDir = userDir * (-1.0f); - stripDirLast = userDir; - } - else { - ++orientationErrors; - } - } - const float *thicknessLast = sv->attribute().getThickness(); - _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thicknessLast[1] * stripDirLast)); - ++i; - _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thicknessLast[0] * stripDirLast)); - ++i; + int i = 2; // 2 because we have already processed the first vertex + + for (vend = iStrokeVertices.end(), ++v, ++v2; v2 != vend; vPrev = v++, ++v2) { + sv = (*v); + sv2 = (*v2); + svPrev = (*vPrev); + Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint()); + + //direction and orthogonal vector to the next segment + Vec2r dir(p2 - p); + float dirNorm = dir.norm(); + dir.normalize(); + Vec2r orthDir(-dir[1], dir[0]); + Vec2r stripDir = orthDir; + if (sv->attribute().isAttributeAvailableVec2f("orientation")) { + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + if (userDir.norm() > 1e-6) { + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDir = userDir; + } + else { + ++orientationErrors; + } + } + + //direction and orthogonal vector to the previous segment + Vec2r dirPrev(p - pPrev); + float dirPrevNorm = dirPrev.norm(); + dirPrev.normalize(); + Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]); + Vec2r stripDirPrev = orthDirPrev; + if (svPrev->attribute().isAttributeAvailableVec2f("orientation")) { + Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation"); + if (userDir.norm() > 1e-6) { + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDirPrev = userDir; + } + else { + ++orientationErrors; + } + } + + const float *thickness = sv->attribute().getThickness(); + _averageThickness += thickness[0] + thickness[1]; + Vec2r pInter; + int interResult; + + interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev + thickness[1] * stripDirPrev), + Vec2r(p + thickness[1] * stripDirPrev), + Vec2r(p + thickness[1] * stripDir), + Vec2r(p2 + thickness[1] * stripDir), + pInter); + if (interResult == GeomUtils::DO_INTERSECT) + _vertices.push_back(new StrokeVertexRep(pInter)); + else + _vertices.push_back(new StrokeVertexRep(p + thickness[1] * stripDir)); + ++i; + + interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev - thickness[0] * stripDirPrev), + Vec2r(p - thickness[0] * stripDirPrev), + Vec2r(p - thickness[0] * stripDir), + Vec2r(p2 - thickness[0] * stripDir), + pInter); + if (interResult == GeomUtils::DO_INTERSECT) + _vertices.push_back(new StrokeVertexRep(pInter)); + else + _vertices.push_back(new StrokeVertexRep(p - thickness[0] * stripDir)); + ++i; + + // if the angle is obtuse, we simply average the directions to avoid the singularity + stripDir = stripDir + stripDirPrev; + if ((dirNorm < ZERO) || (dirPrevNorm < ZERO) || (stripDir.norm() < ZERO)) { + stripDir[0] = 0; + stripDir[1] = 0; + } + else { + stripDir.normalize(); + } + + Vec2r vec_tmp(_vertices[i - 2]->point2d() - p); + if ((vec_tmp.norm() > thickness[1] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || + (dirPrevNorm < ZERO) || notValid(_vertices[i - 2]->point2d()) || + (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER)) { + _vertices[i - 2]->setPoint2d(p + thickness[1] * stripDir); + } + + vec_tmp = _vertices[i - 1]->point2d() - p; + if ((vec_tmp.norm() > thickness[0] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || + (dirPrevNorm < ZERO) || notValid(_vertices[i - 1]->point2d()) || + (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER)) { + _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir); + } + } // end of for + + //special case of last vertex + sv = *v; + sv2 = *vPrev; + dir = Vec2r(sv->getPoint() - sv2->getPoint()); + orthDir = Vec2r(-dir[1], dir[0]); + if (orthDir.norm() > ZERO) + orthDir.normalize(); + Vec2r stripDirLast(orthDir); + // check whether the orientation was user defined + if (sv->attribute().isAttributeAvailableVec2f("orientation")) { + Vec2r userDir = sv->attribute().getAttributeVec2f("orientation"); + if (userDir.norm() > 1e-6) { + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDirLast = userDir; + } + else { + ++orientationErrors; + } + } + const float *thicknessLast = sv->attribute().getThickness(); + _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thicknessLast[1] * stripDirLast)); + ++i; + _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thicknessLast[0] * stripDirLast)); + ++i; #if 0 - int n = i - 1; - // check whether the orientation of the extremity was user defined - userDir = _stroke->getEndingOrientation(); - if (userDir != Vec2r(0, 0)) { - userDir.normalize(); - real o1 = (orthDir * userDir); - real o2 = crossP(orthDir, userDir); - real orientation = o1 * o2; - if (orientation > 0) { - // then the vertex to move is vn - if (o1 < 0) - _vertex[n] = _vertex[n - 1] + userDir; - else - _vertex[n] = _vertex[n - 1] - userDir; - } - if (orientation < 0) { - // then we must move vn-1 - if (o1 > 0) - _vertex[n - 1] = _vertex[n] + userDir; - else - _vertex[n - 1] = _vertex[n] - userDir; - } - } + int n = i - 1; + // check whether the orientation of the extremity was user defined + userDir = _stroke->getEndingOrientation(); + if (userDir != Vec2r(0, 0)) { + userDir.normalize(); + real o1 = (orthDir * userDir); + real o2 = crossP(orthDir, userDir); + real orientation = o1 * o2; + if (orientation > 0) { + // then the vertex to move is vn + if (o1 < 0) + _vertex[n] = _vertex[n - 1] + userDir; + else + _vertex[n] = _vertex[n - 1] - userDir; + } + if (orientation < 0) { + // then we must move vn-1 + if (o1 > 0) + _vertex[n - 1] = _vertex[n] + userDir; + else + _vertex[n - 1] = _vertex[n] - userDir; + } + } #endif - _averageThickness /= float(iStrokeVertices.size() - 2); - //I did not use the first and last vertex for the average - if (iStrokeVertices.size() < 3) - _averageThickness = 0.5 * (thicknessLast[1] + thicknessLast[0] + thickness[0] + thickness[1]); - - if (orientationErrors > 0) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: " << orientationErrors <<" invalid zero-length orientation vector(s) found.\n"; - } - } - - if (i != 2 * (int)iStrokeVertices.size()) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: problem with stripe size\n"; - } - } - - cleanUpSingularities (iStrokeVertices); + _averageThickness /= float(iStrokeVertices.size() - 2); + //I did not use the first and last vertex for the average + if (iStrokeVertices.size() < 3) + _averageThickness = 0.5 * (thicknessLast[1] + thicknessLast[0] + thickness[0] + thickness[1]); + + if (orientationErrors > 0) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: " << orientationErrors + << " invalid zero-length orientation vector(s) found.\n"; + } + } + + if (i != 2 * (int)iStrokeVertices.size()) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: problem with stripe size\n"; + } + } + + cleanUpSingularities(iStrokeVertices); } // CLEAN UP ///////////////////////// -void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices) +void Strip::cleanUpSingularities(const vector<StrokeVertex *> &iStrokeVertices) { - int k; - int sizeStrip = _vertices.size(); - - for (k = 0; k < sizeStrip; k++) { - if (notValid(_vertices[k]->point2d())) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: strip vertex " << k << " non valid" << endl; - } - return; - } - } - - //return; - if (iStrokeVertices.size() < 2) - return; - int i = 0, j; - vector<StrokeVertex *>::const_iterator v, vend, v2; - StrokeVertex *sv, *sv2; - - bool singu1 = false, singu2 = false; - int timeSinceSingu1 = 0, timeSinceSingu2 = 0; - - //special case of first vertex - v = iStrokeVertices.begin(); - for (vend = iStrokeVertices.end(); v != vend; v++) { - v2 = v; - ++v2; - if (v2 == vend) - break; - sv = (*v); - sv2 = (*v2); - Vec2r p(sv->getPoint()), p2(sv2->getPoint()); - - Vec2r dir(p2 - p); - if (dir.norm() > ZERO) - dir.normalize(); - Vec2r dir1, dir2; - dir1 = _vertices[2 * i + 2]->point2d() - _vertices[2 * i]->point2d(); - dir2 = _vertices[2 * i + 3]->point2d() - _vertices[2 * i + 1]->point2d(); - - if ((dir1 * dir) < -ZERO) { - singu1 = true; - timeSinceSingu1++; - } - else { - if (singu1) { - int toto = i - timeSinceSingu1; - if (toto < 0) - cerr << "Stephane dit \"Toto\"" << endl; - //traverse all the vertices of the singularity and average them - Vec2r avP(0.0, 0.0); - for (j = i - timeSinceSingu1; j <= i; j++) - avP = Vec2r(avP + _vertices[2 * j]->point2d()); - avP = Vec2r(1.0 / float(timeSinceSingu1 + 1) * avP); - for (j = i - timeSinceSingu1; j <= i; j++) - _vertices[2 * j]->setPoint2d(avP); - //_vertex[2 * j] = _vertex[2 * i]; - singu1 = false; - timeSinceSingu1 = 0; - } - } - if ((dir2 * dir) < -ZERO) { - singu2 = true; - timeSinceSingu2++; - } - else { - if (singu2) { - int toto = i - timeSinceSingu2; - if (toto < 0) - cerr << "Stephane dit \"Toto\"" << endl; - //traverse all the vertices of the singularity and average them - Vec2r avP(0.0, 0.0); - for (j = i - timeSinceSingu2; j <= i; j++) - avP = Vec2r(avP + _vertices[2 * j + 1]->point2d()); - avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP); - for (j = i - timeSinceSingu2; j <= i; j++) - _vertices[2 * j + 1]->setPoint2d(avP); - //_vertex[2 * j + 1] = _vertex[2 * i + 1]; - singu2 = false; - timeSinceSingu2 = 0; - } - } - i++; - } - - if (singu1) { - //traverse all the vertices of the singularity and average them - Vec2r avP(0.0, 0.0); - for (j = i - timeSinceSingu1; j < i; j++) - avP = Vec2r(avP + _vertices[2 * j]->point2d()); - avP = Vec2r(1.0 / float(timeSinceSingu1) * avP); - for (j = i - timeSinceSingu1; j < i; j++) - _vertices[2 * j]->setPoint2d(avP); - } - if (singu2) { - //traverse all the vertices of the singularity and average them - Vec2r avP(0.0, 0.0); - for (j = i - timeSinceSingu2; j < i; j++) - avP = Vec2r(avP + _vertices[2 * j + 1]->point2d()); - avP = Vec2r(1.0 / float(timeSinceSingu2) * avP); - for (j = i - timeSinceSingu2; j < i; j++) - _vertices[2 * j + 1]->setPoint2d(avP); - } - - for (k = 0; k < sizeStrip; k++) { - if (notValid(_vertices[k]->point2d())) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: strip vertex " << k << " non valid after cleanup" << endl; - } - return; - } - } + int k; + int sizeStrip = _vertices.size(); + + for (k = 0; k < sizeStrip; k++) { + if (notValid(_vertices[k]->point2d())) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: strip vertex " << k << " non valid" << endl; + } + return; + } + } + + //return; + if (iStrokeVertices.size() < 2) + return; + int i = 0, j; + vector<StrokeVertex *>::const_iterator v, vend, v2; + StrokeVertex *sv, *sv2; + + bool singu1 = false, singu2 = false; + int timeSinceSingu1 = 0, timeSinceSingu2 = 0; + + //special case of first vertex + v = iStrokeVertices.begin(); + for (vend = iStrokeVertices.end(); v != vend; v++) { + v2 = v; + ++v2; + if (v2 == vend) + break; + sv = (*v); + sv2 = (*v2); + Vec2r p(sv->getPoint()), p2(sv2->getPoint()); + + Vec2r dir(p2 - p); + if (dir.norm() > ZERO) + dir.normalize(); + Vec2r dir1, dir2; + dir1 = _vertices[2 * i + 2]->point2d() - _vertices[2 * i]->point2d(); + dir2 = _vertices[2 * i + 3]->point2d() - _vertices[2 * i + 1]->point2d(); + + if ((dir1 * dir) < -ZERO) { + singu1 = true; + timeSinceSingu1++; + } + else { + if (singu1) { + int toto = i - timeSinceSingu1; + if (toto < 0) + cerr << "Stephane dit \"Toto\"" << endl; + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0, 0.0); + for (j = i - timeSinceSingu1; j <= i; j++) + avP = Vec2r(avP + _vertices[2 * j]->point2d()); + avP = Vec2r(1.0 / float(timeSinceSingu1 + 1) * avP); + for (j = i - timeSinceSingu1; j <= i; j++) + _vertices[2 * j]->setPoint2d(avP); + //_vertex[2 * j] = _vertex[2 * i]; + singu1 = false; + timeSinceSingu1 = 0; + } + } + if ((dir2 * dir) < -ZERO) { + singu2 = true; + timeSinceSingu2++; + } + else { + if (singu2) { + int toto = i - timeSinceSingu2; + if (toto < 0) + cerr << "Stephane dit \"Toto\"" << endl; + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0, 0.0); + for (j = i - timeSinceSingu2; j <= i; j++) + avP = Vec2r(avP + _vertices[2 * j + 1]->point2d()); + avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP); + for (j = i - timeSinceSingu2; j <= i; j++) + _vertices[2 * j + 1]->setPoint2d(avP); + //_vertex[2 * j + 1] = _vertex[2 * i + 1]; + singu2 = false; + timeSinceSingu2 = 0; + } + } + i++; + } + + if (singu1) { + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0, 0.0); + for (j = i - timeSinceSingu1; j < i; j++) + avP = Vec2r(avP + _vertices[2 * j]->point2d()); + avP = Vec2r(1.0 / float(timeSinceSingu1) * avP); + for (j = i - timeSinceSingu1; j < i; j++) + _vertices[2 * j]->setPoint2d(avP); + } + if (singu2) { + //traverse all the vertices of the singularity and average them + Vec2r avP(0.0, 0.0); + for (j = i - timeSinceSingu2; j < i; j++) + avP = Vec2r(avP + _vertices[2 * j + 1]->point2d()); + avP = Vec2r(1.0 / float(timeSinceSingu2) * avP); + for (j = i - timeSinceSingu2; j < i; j++) + _vertices[2 * j + 1]->setPoint2d(avP); + } + + for (k = 0; k < sizeStrip; k++) { + if (notValid(_vertices[k]->point2d())) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: strip vertex " << k << " non valid after cleanup" << endl; + } + return; + } + } } - // Vertex color (RGBA) //////////////////////////////// -void Strip::setVertexColor (const vector<StrokeVertex *>& iStrokeVertices) +void Strip::setVertexColor(const vector<StrokeVertex *> &iStrokeVertices) { - vector<StrokeVertex *>::const_iterator v, vend; - StrokeVertex *sv; - int i = 0; - for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) { - sv = (*v); - _vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB())); - _vertices[i]->setAlpha(sv->attribute().getAlpha()); - i++; - _vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB())); - _vertices[i]->setAlpha(sv->attribute().getAlpha()); - i++; + vector<StrokeVertex *>::const_iterator v, vend; + StrokeVertex *sv; + int i = 0; + for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) { + sv = (*v); + _vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB())); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; + _vertices[i]->setColor(Vec3r(sv->attribute().getColorRGB())); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; #if 0 - cerr << "col=("<<sv->attribute().getColor()[0] << ", " - << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl; + cerr << "col=("<<sv->attribute().getColor()[0] << ", " + << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl; #endif - } + } } - // Texture coordinates //////////////////////////////// -void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices, float texStep) +void Strip::computeTexCoord(const vector<StrokeVertex *> &iStrokeVertices, float texStep) { - vector<StrokeVertex *>::const_iterator v, vend; - StrokeVertex *sv; - int i = 0; - for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) { - sv = (*v); - _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), 0)); - i++; - _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), -1)); - i++; - } + vector<StrokeVertex *>::const_iterator v, vend; + StrokeVertex *sv; + int i = 0; + for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) { + sv = (*v); + _vertices[i]->setTexCoord( + Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), 0)); + i++; + _vertices[i]->setTexCoord( + Vec2r((real)(sv->curvilinearAbscissa() / (_averageThickness * texStep)), -1)); + i++; + } } -void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd, float texStep) +void Strip::computeTexCoordWithTips(const vector<StrokeVertex *> &iStrokeVertices, + bool tipBegin, + bool tipEnd, + float texStep) { - vector<StrokeVertex*>::const_iterator v, vend; - StrokeVertex *sv = NULL; - StrokeVertexRep *tvRep[2] = {NULL}; - - float l, fact, t; - float u = 0, uPrev = 0; - int tiles; - int i = 0; - float spacedThickness = _averageThickness * texStep; - - v = iStrokeVertices.begin(); - vend = iStrokeVertices.end(); - l = (*v)->strokeLength() / spacedThickness; - tiles = int(l + 0.5); // round to the nearest - fact = (float(tiles) + 0.5) / l; + vector<StrokeVertex *>::const_iterator v, vend; + StrokeVertex *sv = NULL; + StrokeVertexRep *tvRep[2] = {NULL}; + + float l, fact, t; + float u = 0, uPrev = 0; + int tiles; + int i = 0; + float spacedThickness = _averageThickness * texStep; + + v = iStrokeVertices.begin(); + vend = iStrokeVertices.end(); + l = (*v)->strokeLength() / spacedThickness; + tiles = int(l + 0.5); // round to the nearest + fact = (float(tiles) + 0.5) / l; #if 0 - cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess=" - << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl; + cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess=" + << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl; #endif - vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin(); - StrokeVertexRep *svRep; - if (tipBegin) { - for (; v != vend; v++) { - sv = (*v); - svRep = *currentSV; - u = sv->curvilinearAbscissa() / spacedThickness * fact; - if (u > 0.25) - break; - - svRep->setTexCoord(Vec2r((real)u, -0.5), true); - i++; - ++currentSV; - - svRep = *currentSV; - svRep->setTexCoord(Vec2r((real)u, -1), true); - i++; - ++currentSV; - uPrev = u; - } - - if (v != vend && i >= 2) { - // first transition vertex - if (fabs(u - uPrev) > ZERO) - t = (0.25 - uPrev) / (u - uPrev); - else - t = 0; - for (int k = 0; k < 2; k++) { - tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()); - tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + t * _vertices[i]->texCoord()); - // v coord is -0.5 for tvRep[0], -1.0 for tvRep[1] - tvRep[k]->setTexCoord(Vec2r(0.25, -0.5 * (k + 1)), true); - tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + t * Vec3r(sv->attribute().getColorRGB())); - tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); - i++; - } - for (int k = 0; k < 2; k++) { - currentSV = _vertices.insert(currentSV, tvRep[k]); - ++currentSV; - } - - // copy the vertices with different texture coordinates - for (int k = 0; k < 2; k++) { - tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2])); - // v coord is 0.0 for tvRep[0], -0.5 for tvRep[1] - tvRep[k]->setTexCoord(Vec2r(0.0, -0.5 * k), true); - i++; - } - for (int k = 0; k < 2; k++) { - currentSV = _vertices.insert(currentSV, tvRep[k]); - ++currentSV; - } - } - } - uPrev = 0; - - // body of the stroke - for (; v != vend; v++) { - sv = (*v); - svRep = *currentSV; - u = sv->curvilinearAbscissa() / spacedThickness * fact - 0.25; - if (u > tiles) - break; - - svRep->setTexCoord(Vec2r((real)u, 0), true); - i++; - ++currentSV; - - svRep = *currentSV; - svRep->setTexCoord(Vec2r((real)u, -0.5), true); - i++; - ++currentSV; - - uPrev = u; - } - - if (tipEnd) { - if (v != vend && i >= 2) { - // second transition vertex - if (fabs(u - uPrev) > ZERO) - t = (float(tiles) - uPrev) / (u - uPrev); - else - t = 0; - for (int k = 0; k < 2; k++) { - tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()); - tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + t * _vertices[i]->texCoord()); - // v coord is 0.0 for tvRep[0], -0.5 for tvRep[1] - tvRep[k]->setTexCoord(Vec2r((real)tiles, -0.5 * k), true); - tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + t * Vec3r(sv->attribute().getColorRGB())); - tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); - i++; - } - for (int k = 0; k < 2; k++) { - currentSV = _vertices.insert(currentSV, tvRep[k]); - ++currentSV; - } - - // copy the vertices with different texture coordinates - for (int k = 0; k < 2; k++) { - tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2])); - // v coord is -0.5 for tvRep[0], -1.0 for tvRep[1] - tvRep[k]->setTexCoord(Vec2r(0.75, -0.5 * (k + 1)), true); - i++; - } - for (int k = 0; k < 2; k++) { - currentSV = _vertices.insert(currentSV, tvRep[k]); - ++currentSV; - } - } - - // end tip - for (; v != vend; v++) { - sv = (*v); - svRep = *currentSV; - u = 0.75 + sv->curvilinearAbscissa() / spacedThickness * fact - float(tiles) - 0.25; - - svRep->setTexCoord(Vec2r((real)u, -0.5), true); - i++; - ++currentSV; - - svRep = *currentSV; - svRep->setTexCoord(Vec2r((real)u, -1), true); - i++; - ++currentSV; - } - } + vector<StrokeVertexRep *>::iterator currentSV = _vertices.begin(); + StrokeVertexRep *svRep; + if (tipBegin) { + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = sv->curvilinearAbscissa() / spacedThickness * fact; + if (u > 0.25) + break; + + svRep->setTexCoord(Vec2r((real)u, -0.5), true); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, -1), true); + i++; + ++currentSV; + uPrev = u; + } + + if (v != vend && i >= 2) { + // first transition vertex + if (fabs(u - uPrev) > ZERO) + t = (0.25 - uPrev) / (u - uPrev); + else + t = 0; + for (int k = 0; k < 2; k++) { + tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + + t * _vertices[i]->point2d()); + tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + + t * _vertices[i]->texCoord()); + // v coord is -0.5 for tvRep[0], -1.0 for tvRep[1] + tvRep[k]->setTexCoord(Vec2r(0.25, -0.5 * (k + 1)), true); + tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColorRGB())); + tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + } + for (int k = 0; k < 2; k++) { + currentSV = _vertices.insert(currentSV, tvRep[k]); + ++currentSV; + } + + // copy the vertices with different texture coordinates + for (int k = 0; k < 2; k++) { + tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2])); + // v coord is 0.0 for tvRep[0], -0.5 for tvRep[1] + tvRep[k]->setTexCoord(Vec2r(0.0, -0.5 * k), true); + i++; + } + for (int k = 0; k < 2; k++) { + currentSV = _vertices.insert(currentSV, tvRep[k]); + ++currentSV; + } + } + } + uPrev = 0; + + // body of the stroke + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = sv->curvilinearAbscissa() / spacedThickness * fact - 0.25; + if (u > tiles) + break; + + svRep->setTexCoord(Vec2r((real)u, 0), true); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, -0.5), true); + i++; + ++currentSV; + + uPrev = u; + } + + if (tipEnd) { + if (v != vend && i >= 2) { + // second transition vertex + if (fabs(u - uPrev) > ZERO) + t = (float(tiles) - uPrev) / (u - uPrev); + else + t = 0; + for (int k = 0; k < 2; k++) { + tvRep[k] = new StrokeVertexRep((1 - t) * _vertices[i - 2]->point2d() + + t * _vertices[i]->point2d()); + tvRep[k]->setTexCoord((1 - t) * _vertices[i - 2]->texCoord() + + t * _vertices[i]->texCoord()); + // v coord is 0.0 for tvRep[0], -0.5 for tvRep[1] + tvRep[k]->setTexCoord(Vec2r((real)tiles, -0.5 * k), true); + tvRep[k]->setColor((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColorRGB())); + tvRep[k]->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + } + for (int k = 0; k < 2; k++) { + currentSV = _vertices.insert(currentSV, tvRep[k]); + ++currentSV; + } + + // copy the vertices with different texture coordinates + for (int k = 0; k < 2; k++) { + tvRep[k] = new StrokeVertexRep(*(_vertices[i - 2])); + // v coord is -0.5 for tvRep[0], -1.0 for tvRep[1] + tvRep[k]->setTexCoord(Vec2r(0.75, -0.5 * (k + 1)), true); + i++; + } + for (int k = 0; k < 2; k++) { + currentSV = _vertices.insert(currentSV, tvRep[k]); + ++currentSV; + } + } + + // end tip + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = 0.75 + sv->curvilinearAbscissa() / spacedThickness * fact - float(tiles) - 0.25; + + svRep->setTexCoord(Vec2r((real)u, -0.5), true); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, -1), true); + i++; + ++currentSV; + } + } #if 0 - cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl; + cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl; - for (i = 0; i < _sizeStrip; i++) - _alpha[i] = 1.0; + for (i = 0; i < _sizeStrip; i++) + _alpha[i] = 1.0; - for (i = 0; i < _sizeStrip; i++) - cerr << "(" << _texCoord[i][0] << ", " << _texCoord[i][1] << ") "; - cerr << endl; + for (i = 0; i < _sizeStrip; i++) + cerr << "(" << _texCoord[i][0] << ", " << _texCoord[i][1] << ") "; + cerr << endl; - Vec2r vec_tmp; - for (i = 0; i < _sizeStrip / 2; i++) - vec_tmp = _vertex[2 * i] - _vertex[2 * i + 1]; - if (vec_tmp.norm() > 4 * _averageThickness) - cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl; + Vec2r vec_tmp; + for (i = 0; i < _sizeStrip / 2; i++) + vec_tmp = _vertex[2 * i] - _vertex[2 * i + 1]; + if (vec_tmp.norm() > 4 * _averageThickness) + cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl; #endif } @@ -690,128 +706,127 @@ void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertice StrokeRep::StrokeRep() { - _stroke = 0; - _strokeType = Stroke::OPAQUE_MEDIUM; - _nodeTree = NULL; - _hasTex = false; - _textureStep = 1.0; - for (int a = 0; a < MAX_MTEX; a++) { - _mtex[a] = NULL; - } - TextureManager *ptm = TextureManager::getInstance(); - if (ptm) - _textureId = ptm->getDefaultTextureId(); + _stroke = 0; + _strokeType = Stroke::OPAQUE_MEDIUM; + _nodeTree = NULL; + _hasTex = false; + _textureStep = 1.0; + for (int a = 0; a < MAX_MTEX; a++) { + _mtex[a] = NULL; + } + TextureManager *ptm = TextureManager::getInstance(); + if (ptm) + _textureId = ptm->getDefaultTextureId(); #if 0 - _averageTextureAlpha = 0.5; //default value - if (_strokeType == OIL_STROKE) - _averageTextureAlpha = 0.75; - if (_strokeType >= NO_BLEND_STROKE) - _averageTextureAlpha = 1.0 + _averageTextureAlpha = 0.5; //default value + if (_strokeType == OIL_STROKE) + _averageTextureAlpha = 0.75; + if (_strokeType >= NO_BLEND_STROKE) + _averageTextureAlpha = 1.0 #endif } StrokeRep::StrokeRep(Stroke *iStroke) { - _stroke = iStroke; - _strokeType = iStroke->getMediumType(); - _nodeTree = iStroke->getNodeTree(); - _hasTex = iStroke->hasTex(); - _textureId = iStroke->getTextureId(); - _textureStep = iStroke->getTextureStep(); - for (int a = 0; a < MAX_MTEX; a++) { - if (iStroke->getMTex(a)) { - _mtex[a] = iStroke->getMTex(a); - } - else { - _mtex[a] = NULL; - } - } - if (_textureId == 0) { - TextureManager *ptm = TextureManager::getInstance(); - if (ptm) - _textureId = ptm->getDefaultTextureId(); - } + _stroke = iStroke; + _strokeType = iStroke->getMediumType(); + _nodeTree = iStroke->getNodeTree(); + _hasTex = iStroke->hasTex(); + _textureId = iStroke->getTextureId(); + _textureStep = iStroke->getTextureStep(); + for (int a = 0; a < MAX_MTEX; a++) { + if (iStroke->getMTex(a)) { + _mtex[a] = iStroke->getMTex(a); + } + else { + _mtex[a] = NULL; + } + } + if (_textureId == 0) { + TextureManager *ptm = TextureManager::getInstance(); + if (ptm) + _textureId = ptm->getDefaultTextureId(); + } #if 0 - _averageTextureAlpha = 0.5; //default value - if (_strokeType == OIL_STROKE) - _averageTextureAlpha = 0.75; - if (_strokeType >= NO_BLEND_STROKE) - _averageTextureAlpha = 1.0; + _averageTextureAlpha = 0.5; //default value + if (_strokeType == OIL_STROKE) + _averageTextureAlpha = 0.75; + if (_strokeType >= NO_BLEND_STROKE) + _averageTextureAlpha = 1.0; #endif - create(); + create(); } -StrokeRep::StrokeRep(const StrokeRep& iBrother) +StrokeRep::StrokeRep(const StrokeRep &iBrother) { - //soc unused - int i = 0; - _stroke = iBrother._stroke; - _strokeType = iBrother._strokeType; - _textureId = iBrother._textureId; - _textureStep = iBrother._textureStep; - _nodeTree = iBrother._nodeTree; - _hasTex = iBrother._hasTex; - for (int a = 0; a < MAX_MTEX; a++) { - if (iBrother._mtex[a]) { - _mtex[a] = iBrother._mtex[a]; - } - else { - _mtex[a] = NULL; - } - } - for (vector<Strip*>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end(); - s != send; - ++s) - { - _strips.push_back(new Strip(**s)); - } + //soc unused - int i = 0; + _stroke = iBrother._stroke; + _strokeType = iBrother._strokeType; + _textureId = iBrother._textureId; + _textureStep = iBrother._textureStep; + _nodeTree = iBrother._nodeTree; + _hasTex = iBrother._hasTex; + for (int a = 0; a < MAX_MTEX; a++) { + if (iBrother._mtex[a]) { + _mtex[a] = iBrother._mtex[a]; + } + else { + _mtex[a] = NULL; + } + } + for (vector<Strip *>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end(); + s != send; + ++s) { + _strips.push_back(new Strip(**s)); + } } StrokeRep::~StrokeRep() { - if (!_strips.empty()) { - for (vector<Strip*>::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) { - delete (*s); - } - _strips.clear(); - } + if (!_strips.empty()) { + for (vector<Strip *>::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) { + delete (*s); + } + _strips.clear(); + } } void StrokeRep::create() { - vector<StrokeVertex*> strip; - StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd(); - - bool first = true; - bool end = false; - while (v != vend) { - while ((v != vend) && (!(*v).attribute().isVisible())) { - ++v; - first = false; - } - while ((v != vend) && ((*v).attribute().isVisible())) { - strip.push_back(&(*v)); - ++v; - } - if (v != vend) { - // add the last vertex and create - strip.push_back(&(*v)); - } - else { - end = true; - } - if ((!strip.empty()) && (strip.size() > 1)) { - _strips.push_back(new Strip(strip, _hasTex, first, end, _textureStep)); - strip.clear(); - } - first = false; - } + vector<StrokeVertex *> strip; + StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd(); + + bool first = true; + bool end = false; + while (v != vend) { + while ((v != vend) && (!(*v).attribute().isVisible())) { + ++v; + first = false; + } + while ((v != vend) && ((*v).attribute().isVisible())) { + strip.push_back(&(*v)); + ++v; + } + if (v != vend) { + // add the last vertex and create + strip.push_back(&(*v)); + } + else { + end = true; + } + if ((!strip.empty()) && (strip.size() > 1)) { + _strips.push_back(new Strip(strip, _hasTex, first, end, _textureStep)); + strip.clear(); + } + first = false; + } } void StrokeRep::Render(const StrokeRenderer *iRenderer) { - iRenderer->RenderStrokeRep(this); + iRenderer->RenderStrokeRep(this); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h index 3c14d9fa75a..5d58b10184f 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.h +++ b/source/blender/freestyle/intern/stroke/StrokeRep.h @@ -27,11 +27,11 @@ #include "../geometry/Geom.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif extern "C" { -#include "DNA_material_types.h" // for MAX_MTEX +#include "DNA_material_types.h" // for MAX_MTEX struct bNodeTree; } @@ -41,235 +41,242 @@ using namespace Geometry; #if 0 //symbolic constant to call the appropriate renderers and textures -#define NO_TEXTURE_WITH_BLEND_STROKE -2 -#define NO_TEXTURE_STROKE -1 -#define PSEUDO_CHARCOAL_STROKE 0 -#define WASH_BRUSH_STROKE 1 -#define OIL_STROKE 2 -#define NO_BLEND_STROKE 3 -#define CHARCOAL_MIN_STROKE 4 -#define BRUSH_MIN_STROKE 5 -#define OPAQUE_DRY_STROKE 6 -#define OPAQUE_STROKE 7 +# define NO_TEXTURE_WITH_BLEND_STROKE -2 +# define NO_TEXTURE_STROKE -1 +# define PSEUDO_CHARCOAL_STROKE 0 +# define WASH_BRUSH_STROKE 1 +# define OIL_STROKE 2 +# define NO_BLEND_STROKE 3 +# define CHARCOAL_MIN_STROKE 4 +# define BRUSH_MIN_STROKE 5 +# define OPAQUE_DRY_STROKE 6 +# define OPAQUE_STROKE 7 -#define DEFAULT_STROKE 0 +# define DEFAULT_STROKE 0 -#define NUMBER_STROKE_RENDERER 8 +# define NUMBER_STROKE_RENDERER 8 #endif -class StrokeVertexRep -{ -public: - StrokeVertexRep() {} - - StrokeVertexRep(const Vec2r& iPoint2d) - { - _point2d = iPoint2d; - } - - StrokeVertexRep(const StrokeVertexRep& iBrother); - - virtual ~StrokeVertexRep() {} - - inline Vec2r& point2d() - { - return _point2d; - } - - inline Vec2r& texCoord(bool tips=false) - { - if (tips) { - return _texCoord_w_tips; - } - else - return _texCoord; - } - - inline Vec3r& color() - { - return _color; - } - - inline float alpha() - { - return _alpha; - } - - inline void setPoint2d(const Vec2r& p) - { - _point2d = p; - } - - inline void setTexCoord(const Vec2r& p, bool tips=false) - { - if (tips) { - _texCoord_w_tips = p; - } - else { - _texCoord = p; - } - } - - inline void setColor(const Vec3r& p) - { - _color = p; - } - - inline void setAlpha(float a) - { - _alpha = a; - } - -protected: - Vec2r _point2d; - Vec2r _texCoord; - Vec2r _texCoord_w_tips; - Vec3r _color; - float _alpha; +class StrokeVertexRep { + public: + StrokeVertexRep() + { + } + + StrokeVertexRep(const Vec2r &iPoint2d) + { + _point2d = iPoint2d; + } + + StrokeVertexRep(const StrokeVertexRep &iBrother); + + virtual ~StrokeVertexRep() + { + } + + inline Vec2r &point2d() + { + return _point2d; + } + + inline Vec2r &texCoord(bool tips = false) + { + if (tips) { + return _texCoord_w_tips; + } + else + return _texCoord; + } + + inline Vec3r &color() + { + return _color; + } + + inline float alpha() + { + return _alpha; + } + + inline void setPoint2d(const Vec2r &p) + { + _point2d = p; + } + + inline void setTexCoord(const Vec2r &p, bool tips = false) + { + if (tips) { + _texCoord_w_tips = p; + } + else { + _texCoord = p; + } + } + + inline void setColor(const Vec3r &p) + { + _color = p; + } + + inline void setAlpha(float a) + { + _alpha = a; + } + + protected: + Vec2r _point2d; + Vec2r _texCoord; + Vec2r _texCoord_w_tips; + Vec3r _color; + float _alpha; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertexRep") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertexRep") #endif }; -class Strip -{ -public: - typedef std::vector<StrokeVertexRep*> vertex_container; - -protected: - vertex_container _vertices; - float _averageThickness; - -public: - Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTex = false, - bool tipBegin = false, bool tipEnd = false, float texStep = 1.0); - Strip(const Strip& iBrother); - virtual ~Strip(); - -protected: - void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices); - void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices); - void setVertexColor (const std::vector<StrokeVertex*>& iStrokeVertices); - void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices, float texStep); - void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd, float texStep); - -public: - inline int sizeStrip() const - { - return _vertices.size(); - } - - inline vertex_container& vertices() - { - return _vertices; - } +class Strip { + public: + typedef std::vector<StrokeVertexRep *> vertex_container; + + protected: + vertex_container _vertices; + float _averageThickness; + + public: + Strip(const std::vector<StrokeVertex *> &iStrokeVertices, + bool hasTex = false, + bool tipBegin = false, + bool tipEnd = false, + float texStep = 1.0); + Strip(const Strip &iBrother); + virtual ~Strip(); + + protected: + void createStrip(const std::vector<StrokeVertex *> &iStrokeVertices); + void cleanUpSingularities(const std::vector<StrokeVertex *> &iStrokeVertices); + void setVertexColor(const std::vector<StrokeVertex *> &iStrokeVertices); + void computeTexCoord(const std::vector<StrokeVertex *> &iStrokeVertices, float texStep); + void computeTexCoordWithTips(const std::vector<StrokeVertex *> &iStrokeVertices, + bool tipBegin, + bool tipEnd, + float texStep); + + public: + inline int sizeStrip() const + { + return _vertices.size(); + } + + inline vertex_container &vertices() + { + return _vertices; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Strip") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Strip") #endif }; -class StrokeRep -{ -protected: - Stroke *_stroke; - vector<Strip*> _strips; - Stroke::MediumType _strokeType; - unsigned int _textureId; - float _textureStep; - MTex *_mtex[MAX_MTEX]; - bNodeTree *_nodeTree; - Material *_material; - bool _hasTex; - - // float _averageTextureAlpha; - -public: - StrokeRep(); - StrokeRep(const StrokeRep&); - StrokeRep(Stroke *iStroke); - virtual ~StrokeRep(); - - /*! Creates the strips */ - virtual void create(); - - /*! Renders the stroke using a Renderer */ - virtual void Render(const StrokeRenderer *iRenderer); - - /*! accessors */ - inline Stroke::MediumType getMediumType() const - { - return _strokeType; - } - - inline unsigned getTextureId() const - { - return _textureId; - } - - inline MTex *getMTex(int idx) const - { - return _mtex[idx]; - } - - inline Material *getMaterial() const - { - return _material; - } - - inline bNodeTree *getNodeTree() const - { - return _nodeTree; - } - - inline bool hasTex() const - { - return _hasTex; - } - - inline vector<Strip*>& getStrips() - { - return _strips; - } - - inline unsigned int getNumberOfStrips() const - { - return _strips.size(); - } - - inline Stroke *getStroke() - { - return _stroke; - } - - /*! modifiers */ - inline void setMediumType(Stroke::MediumType itype) - { - _strokeType = itype; - } - - inline void setTextureId(unsigned textureId) - { - _textureId = textureId; - } - - inline void setMaterial(Material *mat) - { - _material = mat; - } - /* - inline void setMTex(int idx, MTex *mtex_ptr) - { - _mtex[idx] = mtex_ptr; - }*/ +class StrokeRep { + protected: + Stroke *_stroke; + vector<Strip *> _strips; + Stroke::MediumType _strokeType; + unsigned int _textureId; + float _textureStep; + MTex *_mtex[MAX_MTEX]; + bNodeTree *_nodeTree; + Material *_material; + bool _hasTex; + + // float _averageTextureAlpha; + + public: + StrokeRep(); + StrokeRep(const StrokeRep &); + StrokeRep(Stroke *iStroke); + virtual ~StrokeRep(); + + /*! Creates the strips */ + virtual void create(); + + /*! Renders the stroke using a Renderer */ + virtual void Render(const StrokeRenderer *iRenderer); + + /*! accessors */ + inline Stroke::MediumType getMediumType() const + { + return _strokeType; + } + + inline unsigned getTextureId() const + { + return _textureId; + } + + inline MTex *getMTex(int idx) const + { + return _mtex[idx]; + } + + inline Material *getMaterial() const + { + return _material; + } + + inline bNodeTree *getNodeTree() const + { + return _nodeTree; + } + + inline bool hasTex() const + { + return _hasTex; + } + + inline vector<Strip *> &getStrips() + { + return _strips; + } + + inline unsigned int getNumberOfStrips() const + { + return _strips.size(); + } + + inline Stroke *getStroke() + { + return _stroke; + } + + /*! modifiers */ + inline void setMediumType(Stroke::MediumType itype) + { + _strokeType = itype; + } + + inline void setTextureId(unsigned textureId) + { + _textureId = textureId; + } + + inline void setMaterial(Material *mat) + { + _material = mat; + } + /* + inline void setMTex(int idx, MTex *mtex_ptr) + { + _mtex[idx] = mtex_ptr; + }*/ #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeRep") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeRep") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_REP_H__ +#endif // __FREESTYLE_STROKE_REP_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.cpp b/source/blender/freestyle/intern/stroke/StrokeShader.cpp index 31a212a29f4..b37e137b6f6 100644 --- a/source/blender/freestyle/intern/stroke/StrokeShader.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeShader.cpp @@ -24,9 +24,9 @@ namespace Freestyle { -int StrokeShader::shade(Stroke& ioStroke) const +int StrokeShader::shade(Stroke &ioStroke) const { - return Director_BPy_StrokeShader_shade( const_cast<StrokeShader *>(this), ioStroke); + return Director_BPy_StrokeShader_shade(const_cast<StrokeShader *>(this), ioStroke); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h index 8b4837746e0..3f312395559 100644 --- a/source/blender/freestyle/intern/stroke/StrokeShader.h +++ b/source/blender/freestyle/intern/stroke/StrokeShader.h @@ -26,7 +26,7 @@ #include <vector> #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -60,43 +60,44 @@ class Stroke; * v != vend; * ++v) * { - * StrokeAttribute& att = v->attribute(); - * // perform any attribute modification here... + * StrokeAttribute& att = v->attribute(); + * // perform any attribute modification here... * } * \endcode */ -class StrokeShader -{ -public: - void *py_ss; - - /*! Default constructor. */ - StrokeShader() - { - py_ss = 0; - } - - /*! Destructor. */ - virtual ~StrokeShader() {} - - /*! Returns the string corresponding to the shader's name. */ - virtual string getName() const - { - return "StrokeShader"; - } - - /*! The shading method. This method must be overloaded by inherited classes. - * \param ioStroke: - * The stroke we wish to shade. this Stroke is modified by the Shader (which typically - * modifies the Stroke's attribute's values such as Color, Thickness, Geometry...) - */ - virtual int shade(Stroke& ioStroke) const; +class StrokeShader { + public: + void *py_ss; + + /*! Default constructor. */ + StrokeShader() + { + py_ss = 0; + } + + /*! Destructor. */ + virtual ~StrokeShader() + { + } + + /*! Returns the string corresponding to the shader's name. */ + virtual string getName() const + { + return "StrokeShader"; + } + + /*! The shading method. This method must be overloaded by inherited classes. + * \param ioStroke: + * The stroke we wish to shade. this Stroke is modified by the Shader (which typically + * modifies the Stroke's attribute's values such as Color, Thickness, Geometry...) + */ + virtual int shade(Stroke &ioStroke) const; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeShader") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeShader") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_SHADERS_H__ +#endif // __FREESTYLE_STROKE_SHADERS_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp index bebab7f1bf3..e135f83cfef 100644 --- a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp @@ -30,56 +30,56 @@ namespace Freestyle { LineRep *StrokeTesselator::Tesselate(Stroke *iStroke) { - if (0 == iStroke) - return 0; + if (0 == iStroke) + return 0; - LineRep *line; - line = new OrientedLineRep(); + LineRep *line; + line = new OrientedLineRep(); - Stroke::vertex_iterator v, vend; - if (2 == iStroke->vertices_size()) { - line->setStyle(LineRep::LINES); - v = iStroke->vertices_begin(); - StrokeVertex *svA = (*v); - v++; - StrokeVertex *svB = (*v); - Vec3r A((*svA)[0], (*svA)[1], 0); - Vec3r B((*svB)[0], (*svB)[1], 0); - line->AddVertex(A); - line->AddVertex(B); - } - else { - if (_overloadFrsMaterial) - line->setFrsMaterial(_FrsMaterial); + Stroke::vertex_iterator v, vend; + if (2 == iStroke->vertices_size()) { + line->setStyle(LineRep::LINES); + v = iStroke->vertices_begin(); + StrokeVertex *svA = (*v); + v++; + StrokeVertex *svB = (*v); + Vec3r A((*svA)[0], (*svA)[1], 0); + Vec3r B((*svB)[0], (*svB)[1], 0); + line->AddVertex(A); + line->AddVertex(B); + } + else { + if (_overloadFrsMaterial) + line->setFrsMaterial(_FrsMaterial); - line->setStyle(LineRep::LINE_STRIP); + line->setStyle(LineRep::LINE_STRIP); - for (v = iStroke->vertices_begin(), vend = iStroke->vertices_end(); v != vend; v++) { - StrokeVertex *sv = (*v); - Vec3r V((*sv)[0], (*sv)[1], 0); - line->AddVertex(V); - } - } - line->setId(iStroke->getId()); - line->ComputeBBox(); + for (v = iStroke->vertices_begin(), vend = iStroke->vertices_end(); v != vend; v++) { + StrokeVertex *sv = (*v); + Vec3r V((*sv)[0], (*sv)[1], 0); + line->AddVertex(V); + } + } + line->setId(iStroke->getId()); + line->ComputeBBox(); - return line; + return line; } template<class StrokeVertexIterator> NodeGroup *StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end) { - NodeGroup *group = new NodeGroup; - NodeShape *tshape = new NodeShape; - group->AddChild(tshape); - //tshape->material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f); - tshape->setFrsMaterial(_FrsMaterial); + NodeGroup *group = new NodeGroup; + NodeShape *tshape = new NodeShape; + group->AddChild(tshape); + //tshape->material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f); + tshape->setFrsMaterial(_FrsMaterial); - for (StrokeVertexIterator c = begin, cend = end; c != cend; c++) { - tshape->AddRep(Tesselate((*c))); - } + for (StrokeVertexIterator c = begin, cend = end; c != cend; c++) { + tshape->AddRep(Tesselate((*c))); + } - return group; + return group; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h index 228935f2ab5..8cece705ed4 100644 --- a/source/blender/freestyle/intern/stroke/StrokeTesselator.h +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h @@ -27,51 +27,51 @@ #include "../scene_graph/LineRep.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class StrokeTesselator -{ -public: - inline StrokeTesselator() - { - _FrsMaterial.setDiffuse(0, 0, 0, 1); - _overloadFrsMaterial = false; - } - - virtual ~StrokeTesselator() {} - - /*! Builds a line rep contained from a Stroke */ - LineRep *Tesselate(Stroke *iStroke); - - /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup - * from a set of strokes. - */ - template<class StrokeIterator> - NodeGroup *Tesselate(StrokeIterator begin, StrokeIterator end); - - inline void setFrsMaterial(const FrsMaterial& iMaterial) - { - _FrsMaterial = iMaterial; - _overloadFrsMaterial = true; - } - - inline const FrsMaterial& frs_material() const - { - return _FrsMaterial; - } - -private: - FrsMaterial _FrsMaterial; - bool _overloadFrsMaterial; +class StrokeTesselator { + public: + inline StrokeTesselator() + { + _FrsMaterial.setDiffuse(0, 0, 0, 1); + _overloadFrsMaterial = false; + } + + virtual ~StrokeTesselator() + { + } + + /*! Builds a line rep contained from a Stroke */ + LineRep *Tesselate(Stroke *iStroke); + + /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup + * from a set of strokes. + */ + template<class StrokeIterator> NodeGroup *Tesselate(StrokeIterator begin, StrokeIterator end); + + inline void setFrsMaterial(const FrsMaterial &iMaterial) + { + _FrsMaterial = iMaterial; + _overloadFrsMaterial = true; + } + + inline const FrsMaterial &frs_material() const + { + return _FrsMaterial; + } + + private: + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeTesselator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeTesselator") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STROKE_TESSELATOR_H__ +#endif // __FREESTYLE_STROKE_TESSELATOR_H__ diff --git a/source/blender/freestyle/intern/stroke/StyleModule.h b/source/blender/freestyle/intern/stroke/StyleModule.h index fe902299f9f..64095e971d6 100644 --- a/source/blender/freestyle/intern/stroke/StyleModule.h +++ b/source/blender/freestyle/intern/stroke/StyleModule.h @@ -33,150 +33,152 @@ #include "../system/StringUtils.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; namespace Freestyle { -class StyleModule -{ -public: - StyleModule(const string& file_name, Interpreter *inter) : _file_name(file_name) - { - _always_refresh = false; - _causal = false; - _drawable = true; - _modified = true; - _displayed = true; - _inter = inter; - } - - virtual ~StyleModule() {} - - StrokeLayer *execute() - { - if (!_inter) { - cerr << "Error: no interpreter was found to execute the script" << endl; - return NULL; - } - - if (!_drawable) { - cerr << "Error: not drawable" << endl; - return NULL; - } - - Operators::reset(); - - if (interpret()) { - cerr << "Error: interpretation failed" << endl; - Operators::reset(); - return NULL; - } - - Operators::StrokesContainer *strokes_set = Operators::getStrokesSet(); - if (strokes_set->empty()) { - cerr << "Error: strokes set empty" << endl; - Operators::reset(); - return NULL; - } - - StrokeLayer *sl = new StrokeLayer; - for (Operators::StrokesContainer::iterator it = strokes_set->begin(); it != strokes_set->end(); ++it) - sl->AddStroke(*it); - - Operators::reset(); - return sl; - } - -protected: - virtual int interpret() - { - return _inter->interpretFile(_file_name); - } - -public: - // accessors - const string getFileName() const - { - return _file_name; - } - - bool getAlwaysRefresh() const - { - return _always_refresh; - } - - bool getCausal() const - { - return _causal; - } - - bool getDrawable() const - { - return _drawable; - } - - bool getModified() const - { - return _modified; - } - - bool getDisplayed() const - { - return _displayed; - } - - // modifiers - void setFileName(const string& file_name) - { - _file_name = file_name; - } - - void setAlwaysRefresh(bool b = true) - { - _always_refresh = b; - } - - void setCausal(bool b = true) - { - _causal = b; - } - - void setDrawable(bool b = true) - { - _drawable = b; - } - - void setModified(bool b = true) - { - if (_always_refresh) - return; - _modified = b; - } - - void setDisplayed(bool b = true) - { - _displayed = b; - } - -private: - string _file_name; - bool _always_refresh; - bool _causal; - bool _drawable; - bool _modified; - bool _displayed; - -protected: - Interpreter *_inter; +class StyleModule { + public: + StyleModule(const string &file_name, Interpreter *inter) : _file_name(file_name) + { + _always_refresh = false; + _causal = false; + _drawable = true; + _modified = true; + _displayed = true; + _inter = inter; + } + + virtual ~StyleModule() + { + } + + StrokeLayer *execute() + { + if (!_inter) { + cerr << "Error: no interpreter was found to execute the script" << endl; + return NULL; + } + + if (!_drawable) { + cerr << "Error: not drawable" << endl; + return NULL; + } + + Operators::reset(); + + if (interpret()) { + cerr << "Error: interpretation failed" << endl; + Operators::reset(); + return NULL; + } + + Operators::StrokesContainer *strokes_set = Operators::getStrokesSet(); + if (strokes_set->empty()) { + cerr << "Error: strokes set empty" << endl; + Operators::reset(); + return NULL; + } + + StrokeLayer *sl = new StrokeLayer; + for (Operators::StrokesContainer::iterator it = strokes_set->begin(); it != strokes_set->end(); + ++it) + sl->AddStroke(*it); + + Operators::reset(); + return sl; + } + + protected: + virtual int interpret() + { + return _inter->interpretFile(_file_name); + } + + public: + // accessors + const string getFileName() const + { + return _file_name; + } + + bool getAlwaysRefresh() const + { + return _always_refresh; + } + + bool getCausal() const + { + return _causal; + } + + bool getDrawable() const + { + return _drawable; + } + + bool getModified() const + { + return _modified; + } + + bool getDisplayed() const + { + return _displayed; + } + + // modifiers + void setFileName(const string &file_name) + { + _file_name = file_name; + } + + void setAlwaysRefresh(bool b = true) + { + _always_refresh = b; + } + + void setCausal(bool b = true) + { + _causal = b; + } + + void setDrawable(bool b = true) + { + _drawable = b; + } + + void setModified(bool b = true) + { + if (_always_refresh) + return; + _modified = b; + } + + void setDisplayed(bool b = true) + { + _displayed = b; + } + + private: + string _file_name; + bool _always_refresh; + bool _causal; + bool _drawable; + bool _modified; + bool _displayed; + + protected: + Interpreter *_inter; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StyleModule") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StyleModule") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STYLE_MODULE_H__ +#endif // __FREESTYLE_STYLE_MODULE_H__ diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp index 4b918cd21bc..dc65871ef38 100644 --- a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp @@ -20,58 +20,57 @@ namespace Freestyle { -TextStrokeRenderer::TextStrokeRenderer(const char *iFileName) -:StrokeRenderer() +TextStrokeRenderer::TextStrokeRenderer(const char *iFileName) : StrokeRenderer() { - if (!iFileName) - iFileName = "freestyle.txt"; - // open the stream: - _ofstream.open(iFileName, ios::out); - if (!_ofstream.is_open()) { - cerr << "couldn't open the output file " << iFileName << endl; - } - _ofstream << "%!FREESTYLE" << endl; - _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; - // Bounding box - _ofstream << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << - endl; - _ofstream << "%u x y z tleft tright r g b ..." << endl; + if (!iFileName) + iFileName = "freestyle.txt"; + // open the stream: + _ofstream.open(iFileName, ios::out); + if (!_ofstream.is_open()) { + cerr << "couldn't open the output file " << iFileName << endl; + } + _ofstream << "%!FREESTYLE" << endl; + _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl; + // Bounding box + _ofstream << 0 << " " << 0 << " " << Canvas::getInstance()->width() << " " + << Canvas::getInstance()->height() << endl; + _ofstream << "%u x y z tleft tright r g b ..." << endl; } TextStrokeRenderer::~TextStrokeRenderer() { - Close(); + Close(); } void TextStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const { - RenderStrokeRepBasic(iStrokeRep); + RenderStrokeRepBasic(iStrokeRep); } void TextStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const { - Stroke *stroke = iStrokeRep->getStroke(); - if (!stroke) { - cerr << "no stroke associated with Rep" << endl; - return; - } + Stroke *stroke = iStrokeRep->getStroke(); + if (!stroke) { + cerr << "no stroke associated with Rep" << endl; + return; + } - StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin(); - StrokeAttribute att; - while (!v.isEnd()) { - att = v->attribute(); - _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " << v->getProjectedZ() << - " " << att.getThicknessL() << " " << att.getThicknessR() << " " << - att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " "; - ++v; - } - _ofstream << endl; + StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin(); + StrokeAttribute att; + while (!v.isEnd()) { + att = v->attribute(); + _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " + << v->getProjectedZ() << " " << att.getThicknessL() << " " << att.getThicknessR() + << " " << att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " "; + ++v; + } + _ofstream << endl; } void TextStrokeRenderer::Close() { - if (_ofstream.is_open()) - _ofstream.close(); + if (_ofstream.is_open()) + _ofstream.close(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h index 957ad9c49db..c5af09ef598 100644 --- a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h @@ -48,23 +48,22 @@ namespace Freestyle { /* */ /**********************************/ -class TextStrokeRenderer : public StrokeRenderer -{ -public: - TextStrokeRenderer(const char *iFileName = NULL); - virtual ~TextStrokeRenderer(); +class TextStrokeRenderer : public StrokeRenderer { + public: + TextStrokeRenderer(const char *iFileName = NULL); + virtual ~TextStrokeRenderer(); - /*! Renders a stroke rep */ - virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; - virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; - /*! Closes the output file */ - void Close(); + /*! Closes the output file */ + void Close(); -protected: - mutable ofstream _ofstream; + protected: + mutable ofstream _ofstream; }; } /* namespace Freestyle */ -#endif // TEXTSTROKERENDERER_H +#endif // TEXTSTROKERENDERER_H |