From e5791cf48e10ec1336f463b7fccff6b302621eb9 Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Fri, 28 Dec 2012 20:21:05 +0000 Subject: Another mega (literally :p) code clean-up patch by Bastien Montagne, thanks again! --- .../intern/stroke/AdvancedFunctions0D.cpp | 183 +- .../freestyle/intern/stroke/AdvancedFunctions0D.h | 410 ++-- .../intern/stroke/AdvancedFunctions1D.cpp | 220 +- .../freestyle/intern/stroke/AdvancedFunctions1D.h | 554 ++--- .../freestyle/intern/stroke/AdvancedPredicates1D.h | 149 +- .../intern/stroke/AdvancedStrokeShaders.cpp | 647 +++--- .../intern/stroke/AdvancedStrokeShaders.h | 340 +-- .../freestyle/intern/stroke/BasicStrokeShaders.cpp | 2128 +++++++++--------- .../freestyle/intern/stroke/BasicStrokeShaders.h | 1758 +++++++-------- source/blender/freestyle/intern/stroke/Canvas.cpp | 718 +++--- source/blender/freestyle/intern/stroke/Canvas.h | 383 ++-- source/blender/freestyle/intern/stroke/Chain.cpp | 275 +-- source/blender/freestyle/intern/stroke/Chain.h | 177 +- .../freestyle/intern/stroke/ChainingIterators.cpp | 320 +-- .../freestyle/intern/stroke/ChainingIterators.h | 683 +++--- .../freestyle/intern/stroke/ContextFunctions.cpp | 133 +- .../freestyle/intern/stroke/ContextFunctions.h | 204 +- source/blender/freestyle/intern/stroke/Curve.cpp | 1670 +++++++------- source/blender/freestyle/intern/stroke/Curve.h | 990 +++++---- .../intern/stroke/CurveAdvancedIterators.h | 755 +++---- .../freestyle/intern/stroke/CurveIterators.h | 591 ++--- source/blender/freestyle/intern/stroke/Modifiers.h | 105 +- source/blender/freestyle/intern/stroke/Module.h | 122 +- .../blender/freestyle/intern/stroke/Operators.cpp | 2287 ++++++++++---------- source/blender/freestyle/intern/stroke/Operators.h | 561 +++-- .../freestyle/intern/stroke/PSStrokeRenderer.cpp | 167 +- .../freestyle/intern/stroke/PSStrokeRenderer.h | 96 +- .../blender/freestyle/intern/stroke/Predicates0D.h | 270 +-- .../blender/freestyle/intern/stroke/Predicates1D.h | 1027 ++++----- .../freestyle/intern/stroke/QInformationMap.h | 107 +- source/blender/freestyle/intern/stroke/Stroke.cpp | 1609 +++++++------- source/blender/freestyle/intern/stroke/Stroke.h | 1264 ++++++----- .../intern/stroke/StrokeAdvancedIterators.h | 317 +-- .../blender/freestyle/intern/stroke/StrokeIO.cpp | 110 +- source/blender/freestyle/intern/stroke/StrokeIO.h | 80 +- .../freestyle/intern/stroke/StrokeIterators.h | 444 ++-- .../freestyle/intern/stroke/StrokeLayer.cpp | 92 +- .../blender/freestyle/intern/stroke/StrokeLayer.h | 162 +- .../freestyle/intern/stroke/StrokeRenderer.cpp | 135 +- .../freestyle/intern/stroke/StrokeRenderer.h | 219 +- .../blender/freestyle/intern/stroke/StrokeRep.cpp | 1384 ++++++------ source/blender/freestyle/intern/stroke/StrokeRep.h | 305 ++- .../blender/freestyle/intern/stroke/StrokeShader.h | 165 +- .../freestyle/intern/stroke/StrokeTesselator.cpp | 146 +- .../freestyle/intern/stroke/StrokeTesselator.h | 113 +- .../blender/freestyle/intern/stroke/StyleModule.h | 298 +-- .../freestyle/intern/stroke/TextStrokeRenderer.h | 2 +- 47 files changed, 12930 insertions(+), 11945 deletions(-) (limited to 'source/blender/freestyle/intern/stroke') diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp index 7a51a1a78df..9d955722ac7 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp @@ -1,92 +1,117 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -# include "../view_map/Functions0D.h" -# include "AdvancedFunctions0D.h" -# include "../view_map/SteerableViewMap.h" -# include "Canvas.h" +/** \file blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp + * \ingroup freestyle + * \brief Functions taking 0D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include "AdvancedFunctions0D.h" +#include "Canvas.h" + +#include "../view_map/Functions0D.h" +#include "../view_map/SteerableViewMap.h" namespace Functions0D { - 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; +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(&image, (int)iter->getProjectedX(), - (int)iter->getProjectedY()); + + RGBImage image; + canvas->readColorPixels((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 LocalAverageDepthF0D::operator()(Interface0DIterator& iter) +{ + Canvas * iViewer = Canvas::getInstance(); + int bound = _filter.getBound(); - 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; + 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()); + + 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) { - Canvas * canvas = Canvas::getInstance(); - result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); +int ReadMapPixelF0D::operator()(Interface0DIterator& iter) +{ + Canvas * canvas = Canvas::getInstance(); + result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY()); return 0; - } - - int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - result = svm->readSteerableViewMapPixel(_orientation, _level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); - return 0; - } - - int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) { - SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); - result = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); - return 0; - } - - 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; - } +} + +int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) +{ + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readSteerableViewMapPixel(_orientation, _level, (int)iter->getProjectedX(), + (int)iter->getProjectedY()); + return 0; +} + +int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) +{ + SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap(); + result = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()); + return 0; +} + +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; +} + } // end of namespace Functions0D diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h index 5d62ea8d9eb..2875402700b 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h @@ -1,40 +1,45 @@ -// -// Filename : AdvancedFunctions0D.h -// Author(s) : Stephane Grabli -// Emmanuel Turquin -// Purpose : Functions taking 0D input -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__ +#define __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef ADVANCED_FUNCTIONS0D_HPP -# define ADVANCED_FUNCTIONS0D_HPP +/** \file blender/freestyle/intern/stroke/AdvancedFunctions0D.h + * \ingroup freestyle + * \brief Functions taking 0D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ +#include "../image/GaussianFilter.h" +#include "../image/Image.h" -# include "../image/Image.h" -# include "../image/GaussianFilter.h" -# include "../view_map/Functions0D.h" +#include "../view_map/Functions0D.h" // // Functions definitions @@ -43,167 +48,182 @@ namespace Functions0D { - // DensityF0D - /*! Returns the density of the (result) image evaluated at an Interface0D. - * This density is evaluated using a pixels square window around the - * evaluation point and integrating these values using - * a gaussian. - */ - class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D - { - 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() { - _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 LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D - { - private: - GaussianFilter _filter; - public: - /*! Builds the functor from the size of the mask that - * will be used. - */ - LocalAverageDepthF0D(real maskSize=5.f) : UnaryFunction0D() { - _filter.setSigma((float)maskSize/2.f); - } - /*! Returns the string "LocalAverageDepthF0D"*/ - string getName() const { - return "LocalAverageDepthF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // ReadMapPixel - /*! Reads a pixel in a map. - */ - class LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D - { - 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() { - _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 LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D - { - 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() { - _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 LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D - { - 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() { - _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 LIB_STROKE_EXPORT 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() { - _level = level; - _step = (float)pow(2.0,_level); - } - /*! Returns the string "GetOccludeeF0D"*/ - string getName() const { - return "GetViewMapGradientNormF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; +// DensityF0D +/*! Returns the density of the (result) image evaluated at an Interface0D. + * This density is evaluated using a pixels square window around the evaluation point and integrating + * these values using a gaussian. + */ +class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D +{ +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() + { + _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 LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D +{ +private: + GaussianFilter _filter; + +public: + /*! Builds the functor from the size of the mask that will be used. */ + LocalAverageDepthF0D(real maskSize = 5.0f) : UnaryFunction0D() + { + _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 LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D +{ +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() + { + _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 LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D +{ +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() + { + _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 LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D +{ +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() + { + _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 LIB_STROKE_EXPORT 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() + { + _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 -#endif // ADVANCED_FUNCTIONS0D_HPP +#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 2548ce38659..f757f6ced82 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp @@ -1,110 +1,138 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp + * \ingroup freestyle + * \brief Functions taking 1D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -# include "AdvancedFunctions1D.h" -# include "../view_map/SteerableViewMap.h" -# include "Canvas.h" +#include "AdvancedFunctions1D.h" +#include "Canvas.h" + +#include "../view_map/SteerableViewMap.h" // FIXME namespace Functions1D { - int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) { - SteerableViewMap * svm = Canvas::getInstance()->getSteerableViewMap(); - Interface0DIterator it = inter.pointsBegin(_sampling); - Interface0DIterator itnext = it;++itnext; - FEdge *fe; - unsigned nSVM; - vector 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; - } - float res, res_tmp; - vector::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; - } +int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) +{ + SteerableViewMap * svm = Canvas::getInstance()->getSteerableViewMap(); + Interface0DIterator it = inter.pointsBegin(_sampling); + Interface0DIterator itnext = it; + ++itnext; + FEdge *fe; + unsigned nSVM; + vector 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; + } + + float res, res_tmp; + vector::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) +{ + //soc unsigned size; + result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); + return 0; +} - int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter) { - //soc unsigned size; - result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; - } - - int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) { - //soc unsigned size; - Id id = inter.getId(); - result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration); - return 0; - } +int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) +{ + //soc unsigned size; + Id id = inter.getId(); + 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; - } } +} // Functions1D namespace diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h index ab963c68034..35f516cd781 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h @@ -1,38 +1,44 @@ -// -// Filename : AdvancedFunctions1D.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Functions taking 1D input -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__ +#define __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/AdvancedFunctions1D.h + * \ingroup freestyle + * \brief Functions taking 1D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -#ifndef ADVANCED_FUNCTIONS1D_HPP -# define ADVANCED_FUNCTIONS1D_HPP +#include "AdvancedFunctions0D.h" - -# include "../view_map/Functions1D.h" -# include "AdvancedFunctions0D.h" +#include "../view_map/Functions1D.h" // // Functions definitions @@ -41,248 +47,248 @@ namespace Functions1D { - // DensityF1D - /*! Returns the density evaluated for an Interface1D. - * 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 - { - 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.f) : UnaryFunction1D(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 - /*! Returns the average depth evaluated for an Interface1D. - * 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 - { - 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(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 - /*! Returns the density evaluated for an Interface1D in the - * complete viewmap image. - * 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 LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D - { - 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.f) - : UnaryFunction1D(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 - /*! Returns the density evaluated for an Interface1D in of the - * steerable viewmaps image. - * The direction telling which Directional map to choose - * is explicitely specified by the user. - * 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 LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D - { - 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.f) - : UnaryFunction1D(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 LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D - { - 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.f) : UnaryFunction1D(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 LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D - { - 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.f) - : UnaryFunction1D(iType), _func(level) { - _level = level; - _sampling = sampling; - } - - /*! Returns the string "GetSteerableViewMapDensityF1D"*/ - string getName() const { - return "GetViewMapGradientNormF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; +// DensityF1D +/*! Returns the density evaluated for an Interface1D. + * 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 +{ +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(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 +/*! Returns the average depth evaluated for an Interface1D. + * 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 +{ +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(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 +/*! Returns the density evaluated for an Interface1D in the complete viewmap image. + * 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 LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D +{ +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(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 +/*! Returns the density evaluated for an Interface1D in of the steerable viewmaps image. + * The direction telling which Directional map to choose is explicitely specified by the user. + * 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 LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D +{ +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(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 LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D +{ +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(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 LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D +{ +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(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 -#endif // ADVANCED_FUNCTIONS1D_HPP +#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 91b63168aa9..9235598da78 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h +++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h @@ -1,39 +1,46 @@ -// -// Filename : AdvancedPredicates1D.h -// Author(s) : Stephane Grabli -// Purpose : Class gathering stroke creation algorithms -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_ADVANCED_PREDICATES_1D_H__ +#define __FREESTYLE_ADVANCED_PREDICATES_1D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/AdvancedPredicates1D.h + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \date 01/07/2003 + */ + +#include -#ifndef ADVANCED_PREDICATES1D_H -# define ADVANCED_PREDICATES1D_H +#include "AdvancedFunctions1D.h" +#include "Predicates1D.h" -# include -# include "../view_map/Interface1D.h" -# include "AdvancedFunctions1D.h" -# include "Predicates1D.h" +#include "../view_map/Interface1D.h" // // Predicates definitions @@ -42,43 +49,47 @@ namespace Predicates1D { - // DensityLowerThanUP1D - /*! 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; - } - /*! 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; - } - private: - double _sigma; - double _threshold; - }; +// DensityLowerThanUP1D +/*! 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; + } + + /*! 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; + } + +private: + double _sigma; + double _threshold; +}; } // end of namespace Predicates1D -#endif // ADVANCED_PREDICATES1D_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 7ee5762a70f..e631b9f4471 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp @@ -1,28 +1,42 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp + * \ingroup freestyle + * \brief Fredo's stroke shaders + * \author Fredo Durand + * \date 17/12/2002 + */ #include "AdvancedStrokeShaders.h" +#include "StrokeIterators.h" + #include "../system/PseudoNoise.h" #include "../system/RandGen.h" -#include "StrokeIterators.h" ///////////////////////////////////////// // @@ -30,75 +44,63 @@ // ///////////////////////////////////////// - -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; } -float ksinToto=0; +float ksinToto = 0.0f; -int -CalligraphicShader::shade(Stroke &ioStroke) const +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(&(*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; -} - -//void -//TipRemoverShader::shade(Stroke &ioStroke) const -//{ -// -// StrokeInternal::StrokeVertexIterator v, vend; -// for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); -// v!=vend; -// ++v) -// { -// if (((*v)->curvilinearAbscissa()<_tipLength) || -// ((*v)->strokeLength()-(*v)->curvilinearAbscissa()<_tipLength)) -// { -// (*v)->attribute().setThickness(0.0, 0.0); -// (*v)->attribute().setColor(1,1,1); -// } -// } -// -//} + 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(&(*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; +} +#if 0 +void TipRemoverShader::shade(Stroke &ioStroke) const +{ + StrokeInternal::StrokeVertexIterator v, vend; + for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v) { + if (((*v)->curvilinearAbscissa() < _tipLength) || + (((*v)->strokeLength() - (*v)->curvilinearAbscissa()) < _tipLength)) { + (*v)->attribute().setThickness(0.0, 0.0); + (*v)->attribute().setColor(1, 1, 1); + } + } +} +#endif ///////////////////////////////////////// // @@ -108,99 +110,93 @@ 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 + +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(&(*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(&(*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; - } - - 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(&(*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(&(*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; + } + return 0; +} - ///////////////////////////////////////// // // SMOOTHING SHADER // ///////////////////////////////////////// - -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 +int SmoothingShader::shade(Stroke &ioStroke) const { - //cerr<<" Smoothing a stroke "<getPoint(); - i++; - } - 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); } void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, - real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor) + 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 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 () +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++; - } - + 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; + } } - #if 0 // FIXME ///////////////////////////////////////// @@ -373,63 +352,53 @@ Smoother::copyVertices () // ///////////////////////////////////////// -OmissionShader::OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat) +OmissionShader::OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat) { - _sizeWindow=sizeWindow; - _thresholdVariation=thrVari; - _thresholdFlat=thrFlat; - _lengthFlat=lFlat; + _sizeWindow = sizeWindow; + _thresholdVariation = thrVari; + _thresholdFlat = thrFlat; + _lengthFlat = lFlat; } -int -OmissionShader::shade(Stroke &ioStroke) const +int OmissionShader::shade(Stroke &ioStroke) const { - Omitter omi(ioStroke); - omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat); + Omitter omi(ioStroke); + omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat); - return 0; + return 0; } // OMITTER /////////////////////////// -Omitter::Omitter (Stroke &ioStroke) - :Smoother (ioStroke) +Omitter::Omitter(Stroke &ioStroke) : Smoother(ioStroke) { - StrokeInternal::StrokeVertexIterator v, vend; - int i=0; - for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); - v!=vend; - ++v) - { - _u[i]=(v)->curvilinearAbscissa(); - i++; - } - + StrokeInternal::StrokeVertexIterator v, vend; + int i = 0; + for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v, ++i) { + _u[i] = (v)->curvilinearAbscissa(); + } } -void -Omitter::omit (real sizeWindow, real thrVari, real thrFlat, real lFlat) +void Omitter::omit(real sizeWindow, real thrVari, real thrFlat, real lFlat) { - _sizeWindow=sizeWindow; - _thresholdVariation=thrVari; - _thresholdFlat=thrFlat; - _lengthFlat=lFlat; - - for (int i=1; i<_nbVertices-1; i++) - { - if (_u[i]<_lengthFlat) continue; - // is the previous segment flat? - int j=i-1; - while ((j>=0) && (_u[i]-_u[j]<_lengthFlat)) - { - if ((_normal[j] * _normal[i]) < _thresholdFlat) - ; // FIXME - j--; + _sizeWindow=sizeWindow; + _thresholdVariation=thrVari; + _thresholdFlat=thrFlat; + _lengthFlat=lFlat; + + for (int i = 1; i < _nbVertices-1; ++i) { + if (_u[i] < _lengthFlat) + continue; + // is the previous segment flat? + int j = i - 1; + while ((j >= 0) && (_u[i] - _u[j] < _lengthFlat)) { + if ((_normal[j] * _normal[i]) < _thresholdFlat) + ; // FIXME + --j; + } } - - } } #endif diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h index f2e56222cc0..a957a3f7155 100644 --- a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h +++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h @@ -1,70 +1,73 @@ -// -// Filename : AdvancedStrokeShaders.h -// Author : Fredo Durand -// Purpose : Fredo's stroke shaders -// Date of creation : 17/12/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef ADVANCEDSTROKESHADERS_H -# define ADVANCEDSTROKESHADERS_H - -# include "BasicStrokeShaders.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_ADVANCED_STROKE_SHADERS_H__ +#define __FREESTYLE_ADVANCED_STROKE_SHADERS_H__ + +/** \file blender/freestyle/intern/stroke/AdvancedStrokeShaders.h + * \ingroup freestyle + * \brief Fredo's stroke shaders + * \author Fredo Durand + * \date 17/12/2002 + */ + +#include "BasicStrokeShaders.h" /*! [ Thickness Shader ]. - * Assigns thicknesses to the stroke vertices - * so that the stroke looks like made with a calligraphic tool. - * i.e. The stroke will be the thickest in a main direction, - * the thinest in the direction perpendicular to this one, + * Assigns thicknesses to the stroke vertices so that the stroke looks like made with a calligraphic tool. + * 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 LIB_STROKE_EXPORT CalligraphicShader : public StrokeShader +class LIB_STROKE_EXPORT 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; + /*! 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; + real _maxThickness; + real _minThickness; + Vec2f _orientation; + bool _clamp; }; /*! [ Geometry Shader ]. @@ -72,151 +75,152 @@ protected: * Moves the vertices to make the stroke more noisy. * @see \htmlonly noise/noise.html \endhtmlonly */ -class LIB_STROKE_EXPORT SpatialNoiseShader : public StrokeShader +class LIB_STROKE_EXPORT 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; + /*! 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; + float _amount; + float _xScale; + int _nbOctave; + bool _smooth; + bool _pureRandom; }; /*! [ Geometry Shader ]. * Smoothes the stroke. * (Moves the vertices to make the stroke smoother). - * Uses curvature flow to converge towards a curve of constant - * curvature. The diffusion method we use is anisotropic + * Uses curvature flow to converge towards a curve of constant curvature. The diffusion method we use is anisotropic * to prevent the diffusion accross corners. * @see \htmlonly smoothing/smoothing.html endhtmlonly */ -class LIB_STROKE_EXPORT SmoothingShader : public StrokeShader +class LIB_STROKE_EXPORT 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; + /*! 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; + int _nbIterations; + real _factorPoint; + real _factorCurvature; + real _factorCurvatureDifference; + real _anisoPoint; + real _anisoNormal; + real _anisoCurvature; + real _carricatureFactor; }; class LIB_STROKE_EXPORT Smoother { public: - Smoother (Stroke &ioStroke); - - virtual ~Smoother () {} + 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 (); + 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; + 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 LIB_STROKE_EXPORT Omitter : public Smoother +class LIB_STROKE_EXPORT Omitter : public Smoother { public: - Omitter (Stroke &ioStroke); - virtual ~Omitter () {} + Omitter(Stroke &ioStroke); + + 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; + real *_u; - real _sizeWindow; - real _thresholdVariation; - real _thresholdFlat; - real _lengthFlat; + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; }; -/*! Omission shader - */ -class LIB_STROKE_EXPORT OmissionShader : public StrokeShader +/*! Omission shader */ +class LIB_STROKE_EXPORT OmissionShader : public StrokeShader { public: - OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat); - virtual ~OmissionShader () {} + OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat); + virtual ~OmissionShader() {} - virtual int shade(Stroke &ioStroke) const; + virtual int shade(Stroke &ioStroke) const; protected: - - real _sizeWindow; - real _thresholdVariation; - real _thresholdFlat; - real _lengthFlat; + real _sizeWindow; + real _thresholdVariation; + real _thresholdFlat; + real _lengthFlat; }; -#endif // ADVANCEDSTROKESHADERS_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 eea6da40c9f..852a36571d4 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -1,1170 +1,1108 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/BasicStrokeShaders.cpp + * \ingroup freestyle + * \brief Class gathering basic stroke shaders + * \author Stephane Grabli + * \date 17/12/2002 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "StrokeRenderer.h" #include + +#include "AdvancedFunctions0D.h" +#include "AdvancedFunctions1D.h" #include "BasicStrokeShaders.h" +#include "StrokeIO.h" +#include "StrokeIterators.h" +#include "StrokeRenderer.h" + #include "../system/PseudoNoise.h" #include "../system/RandGen.h" +#include "../system/StringUtils.h" + #include "../view_map/Functions0D.h" #include "../view_map/Functions1D.h" -#include "AdvancedFunctions0D.h" -#include "AdvancedFunctions1D.h" -#include "StrokeIterators.h" -#include "../system/StringUtils.h" -#include "StrokeIO.h" //soc #include //soc #include + extern "C" { -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" +# include "IMB_imbuf.h" +# include "IMB_imbuf_types.h" } // Internal function -// soc -// void convert(const QImage& iImage, float **oArray, unsigned &oSize) { -// oSize = iImage.width(); -// *oArray = new float[oSize]; -// for(unsigned i=0; ix; - *oArray = new float[oSize]; + *oArray = new float[oSize]; char *pix; - for(unsigned i=0; i < oSize; ++i) { - pix = (char*) imBuf->rect + i*4; - (*oArray)[i] = ((float) pix[2] )/255.f; - } + for (unsigned int i = 0; i < oSize; ++i) { + pix = (char*) imBuf->rect + i * 4; + (*oArray)[i] = ((float) pix[2]) / 255.0f; + } } namespace StrokeShaders { - // - // Thickness modifiers - // - ////////////////////////////////////////////////////////// - - 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) - { - 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); - } +// +// Thickness modifiers +// +////////////////////////////////////////////////////////// + +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; - } - - 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) - { - 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); - } +} + +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; - } - - int IncreasingThicknessShader::shade(Stroke& stroke) const - { - - int n=stroke.strokeVerticesSize()-1; - StrokeInternal::StrokeVertexIterator v, vend; - int i=0; - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - - ++v) - { - float t; - if(i < (float)n/2.f) - 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); - ++i; - } +} + +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 ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const - { - float slength = stroke.getLength2D(); - float maxT = min(_ratio*slength,_ThicknessMax); - int n=stroke.strokeVerticesSize()-1; - StrokeInternal::StrokeVertexIterator v, vend; - int i=0; - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - - ++v) - { - float t; - if(i < (float)n/2.f) - 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); - ++i; - } +} + +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; - } - - - int LengthDependingThicknessShader::shade(Stroke& stroke) const - { - float step = (_maxThickness-_minThickness)/3.f; - float l = stroke.getLength2D(); - float thickness = 0.0; - if(l>300.f) - thickness = _minThickness+3.f*step; - else if((l< 300.f) && (l>100.f)) - thickness = _minThickness+2.f*step; - else if((l<100.f) && (l>50.f)) - thickness = _minThickness+1.f*step; - else if(l< 50.f) - thickness = _minThickness; - - StrokeInternal::StrokeVertexIterator v, vend; - int i=0; - int size = stroke.strokeVerticesSize(); - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - ++v) - { - 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); - } +} + + +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; - } - - - ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name, - float iMinThickness, - float iMaxThickness, - bool stretch) - : StrokeShader() { - _stretch = stretch; - _minThickness = iMinThickness; - _maxThickness = iMaxThickness; - ImBuf *image = 0; //soc - vector pathnames; - StringUtils::getPathName(TextureManager::Options::getPatternsPath(), - pattern_name, - pathnames); - for (vector::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { - ifstream ifs(j->c_str()); - if (ifs.is_open()) { - //soc image.load(j->c_str()); - /* OCIO_TODO: support different input color space */ - image = IMB_loadiffname(j->c_str(), 0, NULL); - break; - } - } - if (image == 0) //soc - cerr << "Error: cannot find pattern \"" << pattern_name - << "\" - check the path in the Options" << endl; - else - convert(image, &_aThickness, _size); - } - - int ThicknessVariationPatternShader::shade(Stroke& stroke) const - { - StrokeInternal::StrokeVertexIterator v, vend; - float *array = 0; - int size; - array = _aThickness; - size = _size; - // } - int vert_size = stroke.strokeVerticesSize(); - int sig = 0; - unsigned index; - const float* originalThickness; - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - ++v) - { - originalThickness = v->attribute().getThickness(); - if (_stretch) { - float tmp = v->u()*(_size-1); - index = (unsigned)floor(tmp); - if((tmp-index) > (index+1-tmp)) - ++index; +} + + +ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name, float iMinThickness, + float iMaxThickness, bool stretch) +: StrokeShader() +{ + _stretch = stretch; + _minThickness = iMinThickness; + _maxThickness = iMaxThickness; + ImBuf *image = NULL; //soc + vector pathnames; + StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames); + for (vector::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) { + ifstream ifs(j->c_str()); + if (ifs.is_open()) { + //soc image.load(j->c_str()); + /* OCIO_TODO: support different input color space */ + image = IMB_loadiffname(j->c_str(), 0, NULL); + break; + } } + if (image == NULL) //soc + cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl; else - index = (unsigned)floor(v->curvilinearAbscissa()); - index %= _size; - float thicknessR = array[index]*originalThickness[0]; - float thicknessL = array[index]*originalThickness[1]; - if(thicknessR+thicknessL < _minThickness) - { - thicknessL = _minThickness/2.f; - thicknessR = _minThickness/2.f; - } - if(thicknessR+thicknessL > _maxThickness) - { - thicknessL = _maxThickness/2.f; - thicknessR = _maxThickness/2.f; - } - if((sig==0) || (sig==vert_size-1)) - v->attribute().setThickness(1, 1); - else - v->attribute().setThickness(thicknessR, thicknessL); - ++sig; - } + convert(image, &_aThickness, _size); +} + + +int ThicknessVariationPatternShader::shade(Stroke& stroke) const +{ + StrokeInternal::StrokeVertexIterator v, vend; + float *array = 0; + int size; + array = _aThickness; + size = _size; + int vert_size = stroke.strokeVerticesSize(); + int sig = 0; + unsigned index; + const float* originalThickness; + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + originalThickness = v->attribute().getThickness(); + if (_stretch) { + float tmp = v->u() * (_size - 1); + index = (unsigned)floor(tmp); + if ((tmp - index) > (index + 1 - tmp)) + ++index; + } + else { + index = (unsigned)floor(v->curvilinearAbscissa()); + } + index %= _size; + float thicknessR = array[index] * originalThickness[0]; + float thicknessL = array[index] * originalThickness[1]; + if (thicknessR+thicknessL < _minThickness) { + thicknessL = _minThickness/2.0f; + thicknessR = _minThickness/2.0f; + } + if (thicknessR+thicknessL > _maxThickness) { + thicknessL = _maxThickness/2.0f; + thicknessR = _maxThickness/2.0f; + } + if ((sig == 0) || (sig == vert_size - 1)) + v->attribute().setThickness(1, 1); + else + v->attribute().setThickness(thicknessR, thicknessL); + ++sig; + } return 0; - } - - - static const unsigned NB_VALUE_NOISE = 512; - ThicknessNoiseShader::ThicknessNoiseShader() - :StrokeShader() - {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;} - - ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod) - :StrokeShader() - {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;} - - - int ThicknessNoiseShader::shade(Stroke& stroke) const - { - StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - 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(; - 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); - } - +} + + +static const unsigned NB_VALUE_NOISE = 512; + +ThicknessNoiseShader::ThicknessNoiseShader() : StrokeShader() +{ + _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; +} + +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; - } - - // - // Color shaders - // - /////////////////////////////////////////////////////////////////////////////// - - 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]); - } +} + +// +// Color shaders +// +/////////////////////////////////////////////////////////////////////////////// + +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; - } - - int IncreasingColorShader::shade(Stroke& stroke) const - { - StrokeInternal::StrokeVertexIterator v, vend; - int n=stroke.strokeVerticesSize()-1; - int yo=0; - float newcolor[4]; - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - - ++v) - { - 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]); - ++yo; - } +} + +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; - } - - ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name, - bool stretch) - : StrokeShader() { - _stretch = stretch; - ImBuf *image = 0; //soc - vector pathnames; - StringUtils::getPathName(TextureManager::Options::getPatternsPath(), - pattern_name, - pathnames); - for (vector::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) { - ifstream ifs(j->c_str()); - if (ifs.is_open()) { - /* OCIO_TODO: support different input color space */ - image = IMB_loadiffname(j->c_str(), 0, NULL); //soc - break; - } - } - if (image == 0) //soc - cerr << "Error: cannot find pattern \"" << pattern_name - << "\" - check the path in the Options" << endl; - else - convert(image, &_aVariation, _size); - } - - int ColorVariationPatternShader::shade(Stroke& stroke) const - { - StrokeInternal::StrokeVertexIterator v, vend; - unsigned index; - for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - v!=vend; - ++v) - { - const float *originalColor = v->attribute().getColor(); - if (_stretch) { - float tmp = v->u()*(_size-1); - index = (unsigned)floor(tmp); - if((tmp-index) > (index+1-tmp)) - ++index; +} + +ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name, bool stretch) : StrokeShader() +{ + _stretch = stretch; + ImBuf *image = NULL; //soc + vector pathnames; + StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames); + for (vector::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) { + ifstream ifs(j->c_str()); + if (ifs.is_open()) { + /* OCIO_TODO: support different input color space */ + image = IMB_loadiffname(j->c_str(), 0, NULL); //soc + break; + } } + if (image == NULL) //soc + cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl; else - index = (unsigned)floor(v->curvilinearAbscissa()); - index %= _size; - float r = _aVariation[index]*originalColor[0]; - float g = _aVariation[index]*originalColor[1]; - float b = _aVariation[index]*originalColor[2]; - v->attribute().setColor(r,g,b); - } + convert(image, &_aVariation, _size); +} + +int ColorVariationPatternShader::shade(Stroke& stroke) const +{ + StrokeInternal::StrokeVertexIterator v, vend; + unsigned index; + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) { + const float *originalColor = v->attribute().getColor(); + if (_stretch) { + float tmp = v->u() * (_size - 1); + index = (unsigned)floor(tmp); + if ((tmp - index) > (index + 1 - tmp)) + ++index; + } + else { + index = (unsigned)floor(v->curvilinearAbscissa()); + } + index %= _size; + float r = _aVariation[index] * originalColor[0]; + float g = _aVariation[index] * originalColor[1]; + float b = _aVariation[index] * originalColor[2]; + v->attribute().setColor(r, g, b); + } return 0; - } - - 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(&(*v)); - sv->attribute().setColor(diffuse[0]*_coefficient, diffuse[1]*_coefficient, diffuse[2]*_coefficient); - sv->attribute().setAlpha(diffuse[3]); - } +} + +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(&(*v)); + sv->attribute().setColor(diffuse[0] * _coefficient, diffuse[1] * _coefficient, diffuse[2] * _coefficient); + sv->attribute().setAlpha(diffuse[3]); + } return 0; - } - - - int CalligraphicColorShader::shade(Stroke& stroke) const - { - Interface0DIterator v; - Functions0D::VertexOrientation2DF0D fun; - StrokeVertex* sv; - for(v=stroke.verticesBegin(); - !v.isEnd(); - ++v) - { - if (fun(v) < 0) - return -1; - Vec2f vertexOri(fun.result); - Vec2d ori2d(-vertexOri[1], vertexOri[0]); - ori2d.normalizeSafe(); - real scal = ori2d * _orientation; - sv = dynamic_cast(&(*v)); - if ((scal<0)) - sv->attribute().setColor(0,0,0); - else - sv->attribute().setColor(1,1,1); - } +} + + +int CalligraphicColorShader::shade(Stroke& stroke) const +{ + Interface0DIterator v; + Functions0D::VertexOrientation2DF0D fun; + StrokeVertex *sv; + for (v = stroke.verticesBegin(); !v.isEnd(); ++v) { + if (fun(v) < 0) + return -1; + Vec2f vertexOri(fun.result); + Vec2d ori2d(-vertexOri[1], vertexOri[0]); + ori2d.normalizeSafe(); + real scal = ori2d * _orientation; + sv = dynamic_cast(&(*v)); + if ((scal < 0)) + sv->attribute().setColor(0, 0, 0); + else + sv->attribute().setColor(1, 1, 1); + } return 0; - } - - - ColorNoiseShader::ColorNoiseShader() - :StrokeShader() - {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;} - - ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod) - :StrokeShader() - {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;} - - - int ColorNoiseShader::shade(Stroke& stroke) const - { - StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - real initU=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE); - - real bruit; - PseudoNoise mynoise; - for(; - 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); - } - +} + + +ColorNoiseShader::ColorNoiseShader() : StrokeShader() +{ + _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; +} + +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; - } - - - // - // Texture Shaders - // - /////////////////////////////////////////////////////////////////////////////// - - int TextureAssignerShader::shade(Stroke& stroke) const - { - // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); - // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); - - TextureManager * instance = TextureManager::getInstance(); - if(!instance) - return 0; - string pathname; - Stroke::MediumType mediumType; - bool hasTips = false; - switch(_textureId) - { - case 0: - //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp"; +} + + +// +// Texture Shaders +// +/////////////////////////////////////////////////////////////////////////////// + +int TextureAssignerShader::shade(Stroke& stroke) const +{ +#if 0 + getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); + getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM); +#endif + + TextureManager *instance = TextureManager::getInstance(); + if (!instance) + return 0; + string pathname; + Stroke::MediumType mediumType; + bool hasTips = false; + switch (_textureId) { + case 0: + //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp"; pathname = "/charcoalAlpha.bmp"; - mediumType = Stroke::HUMID_MEDIUM; - hasTips = false; - break; - case 1: - pathname = "/washbrushAlpha.bmp"; - mediumType = Stroke::HUMID_MEDIUM; - hasTips = true; - break; - case 2: - pathname = "/oil.bmp"; - mediumType = Stroke::HUMID_MEDIUM; - hasTips = true; - break; - case 3: - pathname = "/oilnoblend.bmp"; - mediumType = Stroke::HUMID_MEDIUM; - hasTips = true; - break; - case 4: - pathname = "/charcoalAlpha.bmp"; - mediumType = Stroke::DRY_MEDIUM; - hasTips = false; - break; - case 5: - mediumType = Stroke::DRY_MEDIUM; - hasTips = true; - break; - case 6: - pathname = "/opaqueDryBrushAlpha.bmp"; - mediumType = Stroke::OPAQUE_MEDIUM; - hasTips = true; - break; - case 7: - pathname = "/opaqueBrushAlpha.bmp"; - mediumType = Stroke::OPAQUE_MEDIUM; - hasTips = true; - break; - default: - pathname = "/smoothAlpha.bmp"; - mediumType = Stroke::OPAQUE_MEDIUM; - hasTips = false; - break; - } - unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType); - stroke.setMediumType(mediumType); - stroke.setTips(hasTips); - stroke.setTextureId(texId); + mediumType = Stroke::HUMID_MEDIUM; + hasTips = false; + break; + case 1: + pathname = "/washbrushAlpha.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 2: + pathname = "/oil.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 3: + pathname = "/oilnoblend.bmp"; + mediumType = Stroke::HUMID_MEDIUM; + hasTips = true; + break; + case 4: + pathname = "/charcoalAlpha.bmp"; + mediumType = Stroke::DRY_MEDIUM; + hasTips = false; + break; + case 5: + mediumType = Stroke::DRY_MEDIUM; + hasTips = true; + break; + case 6: + pathname = "/opaqueDryBrushAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = true; + break; + case 7: + pathname = "/opaqueBrushAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = true; + break; + default: + pathname = "/smoothAlpha.bmp"; + mediumType = Stroke::OPAQUE_MEDIUM; + hasTips = false; + break; + } + unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType); + stroke.setMediumType(mediumType); + stroke.setTips(hasTips); + stroke.setTextureId(texId); return 0; - } - - // FIXME - int StrokeTextureShader::shade(Stroke& stroke) const - { - TextureManager * instance = TextureManager::getInstance(); - if(!instance) - return 0; - string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath; - unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType); - stroke.setMediumType(_mediumType); - stroke.setTips(_tips); - stroke.setTextureId(texId); +} + +// FIXME +int StrokeTextureShader::shade(Stroke& stroke) const +{ + TextureManager *instance = TextureManager::getInstance(); + if (!instance) + return 0; + string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath; + unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType); + stroke.setMediumType(_mediumType); + stroke.setTips(_tips); + stroke.setTextureId(texId); return 0; - } - - // - // Geometry Shaders - // - /////////////////////////////////////////////////////////////////////////////// - - int BackboneStretcherShader::shade(Stroke& stroke) const - { - float l=stroke.getLength2D(); - if(l <= 1e-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]); +} + +// +// Geometry Shaders +// +/////////////////////////////////////////////////////////////////////////////// + +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; - } +} - int SamplingShader::shade(Stroke& stroke) const - { - stroke.Resample(_sampling); +int SamplingShader::shade(Stroke& stroke) const +{ + stroke.Resample(_sampling); return 0; - } - - int ExternalContourStretcherShader::shade(Stroke& stroke) const - { - //float l=stroke.getLength2D(); - Interface0DIterator it=stroke.verticesBegin(); - Functions0D::Normal2DF0D fun; - StrokeVertex* sv; - while (!it.isEnd()) - { - if (fun(it) < 0) - return -1; - Vec2f n(fun.result); - sv = dynamic_cast(&(*it)); - Vec2d newPoint(sv->x()+_amount*n.x(), sv->y()+_amount*n.y()); - sv->setPoint(newPoint[0], newPoint[1]); - ++it; - } +} + +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(&(*it)); + Vec2d newPoint(sv->x() + _amount * n.x(), sv->y() + _amount * n.y()); + sv->setPoint(newPoint[0], newPoint[1]); + } stroke.UpdateLength(); return 0; - } - - int BSplineShader::shade(Stroke& stroke) const - { - if(stroke.strokeVerticesSize() < 4) - return 0; - - // Find the new vertices - vector newVertices; - double t=0.f; - float _sampling = 5.f; - - StrokeInternal::StrokeVertexIterator p0,p1,p2,p3, end; - p0 = stroke.strokeVerticesBegin(); - p1 = p0; - p2 = p1; - p3 = p2; - end = stroke.strokeVerticesEnd(); - double a[4],b[4]; - int n=0; - while(p1 != end) - { - // if(p1 == end) - // p1 = p0; - if(p2 == end) - p2 = p1; - if(p3 == end) - p3 = p2; - // compute new matrix - a[0] = (-(p0)->x()+3*(p1)->x()-3*(p2)->x()+(p3)->x())/6.0; - a[1] = (3*(p0)->x()-6*(p1)->x()+3*(p2)->x())/6.0; - a[2] = (-3*(p0)->x()+3*(p2)->x())/6.0; - a[3] = ((p0)->x()+4*(p1)->x()+(p2)->x())/6.0; - - b[0] = (-(p0)->y()+3*(p1)->y()-3*(p2)->y()+(p3)->y())/6.0; - b[1] = (3*(p0)->y()-6*(p1)->y()+3*(p2)->y())/6.0; - b[2] = (-3*(p0)->y()+3*(p2)->y())/6.0; - b[3] = ((p0)->y()+4*(p1)->y()+(p2)->y())/6.0; - - - // draw the spline depending on resolution: - Vec2d p1p2((p2)->x()-(p1)->x(), (p2)->y()-(p1)->y()); - double norm = p1p2.norm(); - //t = _sampling/norm; - t=0; - while(t<1) - { - newVertices.push_back(Vec2d((a[3] + t*(a[2] + t*(a[1] + t*a[0]))), - (b[3] + t*(b[2] + t*(b[1] + t*b[0]))))); - t = t + _sampling/norm; - } - if(n > 2) - { - ++p0; - ++p1; - ++p2; - ++p3; - } - else - { - if(n==0) - ++p3; - if(n==1) - {++p2;++p3;} - if(n==2) - {++p1;++p2;++p3;} - ++n; - } - } - //last point: - newVertices.push_back(Vec2d((p0)->x(), (p0)->y())); - - int originalSize = newVertices.size(); - _sampling = stroke.ComputeSampling(originalSize); - - // Resample and set x,y coordinates - stroke.Resample(_sampling); - int newsize = stroke.strokeVerticesSize(); - - int nExtraVertex=0; - if(newsize < originalSize) - cerr << "Warning: unsufficient resampling" << endl; - else - { - nExtraVertex = newsize - originalSize; - } - - // assigns the new coordinates: - vector::iterator p,pend; - p=newVertices.begin();pend=newVertices.end(); - vector::iterator last = p; - n=0; - StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd(); - it=stroke.strokeVerticesBegin(); - for(; - ((it!=itend) && (p!=pend)); - ++it) - { - it->setX(p->x()); - it->setY(p->y()); - last = p; - ++p; - ++n; - } - // nExtraVertex should stay unassigned - for(int i=0; i< nExtraVertex; ++i) - { - it->setX(last->x()); - it->setY(last->y()); - if(it.isEnd()) - cerr << "Warning: Problem encountered while creating B-spline" << endl; - ++it; - ++n; - } +} + +int BSplineShader::shade(Stroke& stroke) const +{ + if (stroke.strokeVerticesSize() < 4) + return 0; + + // Find the new vertices + vector newVertices; + double t = 0.0; + float _sampling = 5.0f; + + StrokeInternal::StrokeVertexIterator p0, p1, p2, p3, end; + p0 = stroke.strokeVerticesBegin(); + p1 = p0; + p2 = p1; + p3 = p2; + end = stroke.strokeVerticesEnd(); + double a[4], b[4]; + int n = 0; + while (p1 != end) { +#if 0 + if (p1 == end) + p1 = p0; +#endif + if (p2 == end) + p2 = p1; + if (p3 == end) + p3 = p2; + // compute new matrix + a[0] = (-(p0)->x() + 3 * (p1)->x() - 3 * (p2)->x() + (p3)->x()) / 6.0; + a[1] = (3 * (p0)->x() - 6 * (p1)->x() + 3 * (p2)->x()) / 6.0; + a[2] = (-3 * (p0)->x() + 3 * (p2)->x()) / 6.0; + a[3] = ((p0)->x() + 4 * (p1)->x() + (p2)->x()) / 6.0; + + b[0] = (-(p0)->y() + 3 * (p1)->y() - 3 * (p2)->y() + (p3)->y()) / 6.0; + b[1] = (3 * (p0)->y() - 6 * (p1)->y() + 3 * (p2)->y()) / 6.0; + b[2] = (-3 * (p0)->y() + 3 * (p2)->y()) / 6.0; + b[3] = ((p0)->y() + 4 * (p1)->y() + (p2)->y()) / 6.0; + + // draw the spline depending on resolution: + Vec2d p1p2((p2)->x() - (p1)->x(), (p2)->y() - (p1)->y()); + double norm = p1p2.norm(); + //t = _sampling / norm; + t = 0; + while (t < 1) { + newVertices.push_back(Vec2d((a[3] + t * (a[2] + t * (a[1] + t * a[0]))), + (b[3] + t * (b[2] + t * (b[1] + t * b[0]))))); + t = t + _sampling / norm; + } + if (n > 2) { + ++p0; + ++p1; + ++p2; + ++p3; + } + else { + if (n == 0) + ++p3; + if (n == 1) { + ++p2; + ++p3; + } + if (n == 2) { + ++p1; + ++p2; + ++p3; + } + ++n; + } + } + //last point: + newVertices.push_back(Vec2d((p0)->x(), (p0)->y())); + + int originalSize = newVertices.size(); + _sampling = stroke.ComputeSampling(originalSize); + + // Resample and set x,y coordinates + stroke.Resample(_sampling); + int newsize = stroke.strokeVerticesSize(); + + int nExtraVertex = 0; + if (newsize < originalSize) { + cerr << "Warning: unsufficient resampling" << endl; + } + else { + nExtraVertex = newsize - originalSize; + } + + // assigns the new coordinates: + vector::iterator p = newVertices.begin(), pend = newVertices.end(); + vector::iterator last = p; + n = 0; + StrokeInternal::StrokeVertexIterator it, itend; + for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(); + (it != itend) && (p != pend); + ++it, ++p, ++n) + { + it->setX(p->x()); + it->setY(p->y()); + last = p; + } + + // nExtraVertex should stay unassigned + for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) { + it->setX(last->x()); + it->setY(last->y()); + if (it.isEnd()) { + // XXX Shouldn't we break in this case??? + cerr << "Warning: Problem encountered while creating B-spline" << endl; + } + } stroke.UpdateLength(); return 0; - } - - //!! Bezier curve stroke shader - int BezierCurveShader::shade(Stroke& stroke) const - { - if(stroke.strokeVerticesSize() < 4) - return 0; - - // Build the Bezier curve from this set of data points: - vector data; - StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd(); - data.push_back(Vec2d(v->x(), v->y()));//first one - StrokeInternal::StrokeVertexIterator previous = v;++v; - for(; - v!=vend; - ++v) - { - if(!((fabs(v->x() -(previous)->x())y() - (previous)->y())x(), v->y())); - previous = v; - } - - // Vec2d tmp;bool equal=false; - // if(data.front() == data.back()) - // { - // tmp = data.back(); - // data.pop_back(); - // equal=true; - // } - // here we build the bezier curve - BezierCurve bcurve(data, _error); - - // bad performances are here !!! // FIXME - vector CurveVertices; - vector& bsegments = bcurve.segments(); - vector::iterator s=bsegments.begin(),send=bsegments.end(); - vector& segmentsVertices = (*s)->vertices(); - vector::iterator p,pend; - // first point - CurveVertices.push_back(segmentsVertices[0]); - for(; - s!=send; - ++s) - { - segmentsVertices = (*s)->vertices(); - p=segmentsVertices.begin(); pend=segmentsVertices.end(); - ++p; - for(; - p!=pend; - ++p) - { - CurveVertices.push_back((*p)); - } - } - - //if(equal) - // if(data.back() == data.front()) - // { - // vector::iterator d=data.begin(), dend=data.end(); - // cout << "ending point = starting point" << endl; - // cout << "---------------DATA----------" << endl; - // for(; - // d!=dend; - // ++d) - // { - // cout << d->x() << "-" << d->y() << endl; - // } - // cout << "--------------BEZIER RESULT----------" << endl; - // d=CurveVertices.begin(), dend=CurveVertices.end(); - // for(;d!=dend;++d) - // { - // cout << d->x() << "-" << d->y() << endl; - // } - // } - - // Resample the Stroke depending on the number of - // vertices of the bezier curve: - int originalSize = CurveVertices.size(); - //float sampling = stroke.ComputeSampling(originalSize); - //stroke.Resample(sampling); - stroke.Resample(originalSize); - int newsize = stroke.strokeVerticesSize(); - int nExtraVertex=0; - if(newsize < originalSize) - cerr << "Warning: unsufficient resampling" << endl; - else - { - //cout << "Oversampling" << endl; - nExtraVertex = newsize - originalSize; - if(nExtraVertex != 0) - cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl; - } - - // assigns the new coordinates: - p=CurveVertices.begin();pend=CurveVertices.end(); - vector::iterator last = p; - int n=0; - StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd(); - // while(p!=pend) - // { - // ++n; - // ++p; - // } - it=stroke.strokeVerticesBegin(); - for(; - ((it!=itend) && (p!=pend)); - ++it) - { - it->setX(p->x()); - it->setY(p->y()); - // double x = p->x(); - // double y = p->y(); - // cout << "x = " << x << "-" << "y = " << y << endl; - last = p; - ++p; - ++n; - } +} + +//!! Bezier curve stroke shader +int BezierCurveShader::shade(Stroke& stroke) const +{ + if (stroke.strokeVerticesSize() < 4) + return 0; + + // Build the Bezier curve from this set of data points: + vector 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; + } + +#if 0 + Vec2d tmp; + bool equal = false; + if (data.front() == data.back()) { + tmp = data.back(); + data.pop_back(); + equal = true; + } +#endif + // here we build the bezier curve + BezierCurve bcurve(data, _error); + + // bad performances are here !!! // FIXME + vector CurveVertices; + vector& bsegments = bcurve.segments(); + vector::iterator s = bsegments.begin(), send; + vector& segmentsVertices = (*s)->vertices(); + vector::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)); + } + } + +#if 0 + if (equal) { + if (data.back() == data.front()) { + vector::iterator d = data.begin(), dend; + cout << "ending point = starting point" << endl; + cout << "---------------DATA----------" << endl; + for (dend = data.end(); d != dend; ++d) { + cout << d->x() << "-" << d->y() << endl; + } + cout << "--------------BEZIER RESULT----------" << endl; + for (d = CurveVertices.begin(), dend = CurveVertices.end(); d != dend; ++d) { + cout << d->x() << "-" << d->y() << endl; + } + } + } +#endif + + // 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); +#endif + stroke.Resample(originalSize); + int newsize = stroke.strokeVerticesSize(); + int nExtraVertex = 0; + if (newsize < originalSize) { + cerr << "Warning: unsufficient resampling" << endl; + } + else { + //cout << "Oversampling" << endl; + nExtraVertex = newsize - originalSize; + if (nExtraVertex != 0) + cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl; + } + + // assigns the new coordinates: + p = CurveVertices.begin(); + vector::iterator last = p; + int n; + StrokeInternal::StrokeVertexIterator it, itend; +#if 0 + for (; p != pend; ++n, ++p); +#endif + 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()); +#if 0 + double x = p->x(); + double y = p->y(); + cout << "x = " << x << "-" << "y = " << y << endl; +#endif + last = p; + } stroke.UpdateLength(); - // Deal with extra vertices: - if(nExtraVertex == 0) - return 0; - - // nExtraVertex should stay unassigned - vector attributes; - vector verticesToRemove; - for(int i=0; i< nExtraVertex; ++i) - { - verticesToRemove.push_back(&(*it)); - if(it.isEnd()) - cout << "fucked up" << endl; - ++it; - ++n; - } - it=stroke.strokeVerticesBegin(); - for(; - it!=itend; - ++it) - { - attributes.push_back(it->attribute()); - } - - for(vector::iterator vr=verticesToRemove.begin(), vrend=verticesToRemove.end(); - vr!=vrend; - ++vr) - { - stroke.RemoveVertex(*vr); - } - it=stroke.strokeVerticesBegin(); - itend=stroke.strokeVerticesEnd(); - vector::iterator a=attributes.begin(), aend=attributes.end(); - int index = 0; - int index1 = (int)floor((float)originalSize/2.0); - int index2 = index1+nExtraVertex; - for(; - (it!=itend) && (a!=aend); - ++it) - { - (it)->setAttribute(*a); - if((index <= index1)||(index>index2)) - ++a; - ++index; - } + // Deal with extra vertices: + if (nExtraVertex == 0) + return 0; + + // nExtraVertex should stay unassigned + vector attributes; + vector 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??? + cout << "fucked up" << endl; + } + } + for (it = stroke.strokeVerticesBegin(); it != itend; ++it) { + attributes.push_back(it->attribute()); + } + + for (vector::iterator vr = verticesToRemove.begin(), vrend = verticesToRemove.end(); + vr != vrend; + ++vr) + { + stroke.RemoveVertex(*vr); + } + + vector::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; - } +} - int InflateShader::shade(Stroke& stroke) const - { - // we're computing the curvature variance of the stroke.(Combo 5) - // If it's too high, forget about it - Functions1D::Curvature2DAngleF1D fun; +int InflateShader::shade(Stroke& stroke) const +{ + // we're computing the curvature variance of the stroke. (Combo 5) + // If it's too high, forget about it + Functions1D::Curvature2DAngleF1D fun; if (fun(stroke) < 0) - return -1; + return -1; if (fun.result > _curvatureThreshold) - return 0; - - Functions0D::VertexOrientation2DF0D ori_fun; - Functions0D::Curvature2DAngleF0D curv_fun; - Functions1D::Normal2DF1D norm_fun; - Interface0DIterator it=stroke.verticesBegin(); - StrokeVertex* sv; - while (!it.isEnd()) - { - if (ori_fun(it) < 0) - return -1; - Vec2f ntmp(ori_fun.result); - Vec2f n(ntmp.y(), -ntmp.x()); - if (norm_fun(stroke) < 0) - return -1; - Vec2f strokeN(norm_fun.result); - if(n*strokeN < 0) - { - n[0] = -n[0]; - n[1] = -n[1]; - } - sv = dynamic_cast(&(*it)); - float u=sv->u(); - float t = 4.f*(0.25f - (u-0.5)*(u-0.5)); - if (curv_fun(it) < 0) - return -1; - float curvature_coeff = (M_PI-curv_fun.result)/M_PI; - Vec2d newPoint(sv->x()+curvature_coeff*t*_amount*n.x(), sv->y()+curvature_coeff*t*_amount*n.y()); - sv->setPoint(newPoint[0], newPoint[1]); - ++it; - } + return 0; + + Functions0D::VertexOrientation2DF0D ori_fun; + Functions0D::Curvature2DAngleF0D curv_fun; + Functions1D::Normal2DF1D norm_fun; + Interface0DIterator it; + StrokeVertex *sv; + for (it = stroke.verticesBegin(); !it.isEnd(); ++it) { + if (ori_fun(it) < 0) + return -1; + Vec2f ntmp(ori_fun.result); + Vec2f n(ntmp.y(), -ntmp.x()); + if (norm_fun(stroke) < 0) + return -1; + Vec2f strokeN(norm_fun.result); + if (n*strokeN < 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + sv = dynamic_cast(&(*it)); + float u = sv->u(); + float t = 4.0f * (0.25f - (u - 0.5) * (u - 0.5)); + if (curv_fun(it) < 0) + return -1; + float curvature_coeff = (M_PI - curv_fun.result) / M_PI; + Vec2d newPoint(sv->x() + curvature_coeff * t * _amount * n.x(), + sv->y() + curvature_coeff * t * _amount * n.y()); + sv->setPoint(newPoint[0], newPoint[1]); + } stroke.UpdateLength(); 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) - { - _begin = b; - _last = l; - A = Vec2d((_begin)->x(),(_begin)->y()); - B = Vec2d((_last)->x(),(_last)->y()); - size = iSize; - } - - float error() - { - float maxE = 0.f; - for(StrokeInternal::StrokeVertexIterator it=_begin; - it!=_last; - ++it) +} + +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) { - Vec2d P(it->x(), it->y()); - float d = GeomUtils::distPointSegment(P,A,B); - if(d > maxE) - maxE = d; + _begin = b; + _last = l; + A = Vec2d((_begin)->x(), (_begin)->y()); + B = Vec2d((_last)->x(), (_last)->y()); + size = iSize; } - _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 actualSize = 1; - for(int i=0; ix(), 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 actualSize = (size > 1) ? size / 2 : 1; + for (int i = 0; i <= actualSize; ++it, ++i); + + CurvePiece *second = new CurvePiece(it, _last, size - actualSize + 1); + size = actualSize; + _last = it; + B = Vec2d((_last)->x(), (_last)->y()); + return second; + } +}; + +int PolygonalizationShader::shade(Stroke& stroke) const +{ + vector _pieces; + vector _results; + vector::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->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); +#endif } - CurvePiece * second = new CurvePiece(it, _last, size-actualSize+1); - size = actualSize; - _last = it; - B = Vec2d((_last)->x(), (_last)->y()); - return second; - } - }; - - int PolygonalizationShader::shade(Stroke& stroke) const - { - vector _pieces; - vector _results; - vector::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->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,vlast; - 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); - } - // u.normalize(); - // (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10); - } stroke.UpdateLength(); - // delete stuff - for(cp=_results.begin(), cpend=_results.end(); - cp!=cpend; - ++cp) - { - delete (*cp); - } - _results.clear(); + // delete stuff + for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) { + delete (*cp); + } + _results.clear(); return 0; - } - - 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(); +} + +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.f*_offset; - StrokeInternal::StrokeVertexIterator v=a,vend=stroke.strokeVerticesEnd(); - for(; - 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); - } + 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; - } - - ///////////////////////////////////////// - // - // Tip Remover - // - ///////////////////////////////////////// - - - TipRemoverShader::TipRemoverShader(real tipLength) - : StrokeShader() - { - _tipLength = tipLength; - } - - int - TipRemoverShader::shade(Stroke& stroke) const - { - int originalSize = stroke.strokeVerticesSize(); - - if(originalSize<4) - return 0; - - StrokeInternal::StrokeVertexIterator v, vend; - vector verticesToRemove; - vector oldAttributes; - v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd(); - for(; - 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::iterator sv=verticesToRemove.begin(), svend=verticesToRemove.end(); - for(; - 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: - v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd(); - vector::iterator a=oldAttributes.begin(), aend=oldAttributes.end(); - //cout << "-----------------------------------------------" << endl; - for(;(v!=vend)&&(a!=aend);++v,++a) - { - v->setAttribute(*a); - //cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl; - } - // we're done! +} + +///////////////////////////////////////// +// +// Tip Remover +// +///////////////////////////////////////// + + +TipRemoverShader::TipRemoverShader(real tipLength) : StrokeShader() +{ + _tipLength = tipLength; +} + +int TipRemoverShader::shade(Stroke& stroke) const +{ + int originalSize = stroke.strokeVerticesSize(); + + if (originalSize < 4) + return 0; + + StrokeInternal::StrokeVertexIterator v, vend; + vector verticesToRemove; + vector 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::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::iterator a = oldAttributes.begin(), aend = oldAttributes.end(); + //cout << "-----------------------------------------------" << endl; + for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); + (v != vend) && (a != aend); + ++v, ++a) + { + v->setAttribute(*a); + //cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl; + } + // we're done! return 0; - } +} - int streamShader::shade(Stroke& stroke) const{ - cout << stroke << endl; +int streamShader::shade(Stroke& stroke) const +{ + cout << stroke << endl; return 0; - } - int fstreamShader::shade(Stroke& stroke) const{ - _stream << stroke << endl; +} + +int fstreamShader::shade(Stroke& stroke) const +{ + _stream << stroke << endl; return 0; - } +} } // end of namespace StrokeShaders - diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h index a0c0a44c9b6..33919b65f21 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h @@ -1,890 +1,902 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_BASIC_STROKE_SHADERS_H__ +#define __FREESTYLE_BASIC_STROKE_SHADERS_H__ + +/** \file blender/freestyle/intern/stroke/BasicStrokeShaders.h + * \ingroup freestyle + * \brief Class gathering basic stroke shaders + * \author Stephane Grabli + * \date 17/12/2002 + */ + +#include + +#include "Stroke.h" +#include "StrokeShader.h" + +#include "../geometry/Bezier.h" +#include "../geometry/Geom.h" + +using namespace std; +using namespace Geometry; + +namespace StrokeShaders { + // -// Filename : BasicStrokeShaders.h -// Author : Stephane Grabli -// Purpose : Class gathering basic stroke shaders -// Date of creation : 17/12/2002 +// Thickness modifiers // -/////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////// + +/*! [ Thickness Shader ]. + * Assigns an absolute constant thickness to every vertices of the Stroke. + */ +class LIB_STROKE_EXPORT 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 ]. + * Assigns an absolute constant external thickness to every vertices of the Stroke. The external thickness of a point + * is its thickness from the point to the strip border in the direction pointing outside the object the + * Stroke delimitates. + */ +class LIB_STROKE_EXPORT 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 ]. + * Assigns thicknesses values such as the thickness increases from a thickness value A to a thickness value B between + * the first vertex to the midpoint vertex and then decreases from B to a A between this midpoint vertex + * and the last vertex. + * The thickness is linearly interpolated from A to B. + */ +class LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 ]. +* Applys a pattern (texture) to vary thickness. +* The new thicknesses are the result of the multiplication +* of the pattern and the original thickness +*/ +class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader +{ +public: + /*! Builds the shader. + * \param pattern_name + * The texture file name. + * \param iMinThickness + * The minimum thickness we don't want to exceed. + * \param iMaxThickness + * The maximum thickness we don't want to exceed. + * \param stretch + * Tells whether the pattern texture must be stretched or repeted to fit the stroke. + */ + ThicknessVariationPatternShader(const string pattern_name, float iMinThickness = 1.0f, float iMaxThickness = 5.0f, + bool stretch = true); + + /*! Destructor.*/ + virtual ~ThicknessVariationPatternShader() + { + if (0 != _aThickness) { + delete[] _aThickness; + _aThickness = 0; + } + } + virtual string getName() const + { + return "ThicknessVariationPatternShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + +private: + float *_aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1) + unsigned _size; + float _minThickness; + float _maxThickness; + bool _stretch; +}; + +/*! [ Thickness Shader ]. + * Adds some noise to the stroke thickness. + * \see \htmlonly noise/noise.html\endhtmlonly + */ +class LIB_STROKE_EXPORT 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 // -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. +///////////////////////////////////////////////////////// +/*! [ Color Shader ]. + * Assigns a constant color to every vertices of the Stroke. + */ +class LIB_STROKE_EXPORT 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 ]. + * Assigns a varying color to the stroke. + * 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 LIB_STROKE_EXPORT 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 ]. + * Applys a pattern to vary original color. + * The new color is the result of the multiplication of the pattern and the original color + */ +class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader +{ +public: + /*! Builds the shader from the pattern texture file name. + * \param pattern_name + * The file name of the texture file to use as pattern + * \param stretch + * Tells whether the texture must be strecthed or repeted to fit the stroke. + */ + ColorVariationPatternShader(const string pattern_name, bool stretch = true); + + /*! Destructor */ + virtual ~ColorVariationPatternShader() + { + if (0 != _aVariation) { + delete[] _aVariation; + _aVariation = 0; + } + } + + virtual string getName() const + { + return "ColorVariationPatternShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; + +private: + float *_aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1) + unsigned _size; + bool _stretch; +}; + +/* [ Color Shader ]. + * Assigns a color to the stroke depending on the material of the shape to which ot belongs to. (Disney shader) + */ +class LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader +{ +private: + int _textureId; + Vec2d _orientation; + +public: + CalligraphicColorShader(const Vec2d &iOrientation) : StrokeShader() + { + _orientation = iOrientation; + _orientation.normalize(); + } + + virtual string getName() const + { + return "CalligraphicColorShader"; + } + + virtual int shade(Stroke& stroke) const; +}; + +/*! [ Color Shader ]. + * Shader to add noise to the stroke colors. + */ +class LIB_STROKE_EXPORT 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; +}; + // -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// Texture Shaders // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +/////////////////////////////////////////////////////////////////////////////// +/*! [ Texture Shader ]. +* Assigns a texture to the stroke in order to simulate +* its marks system. This shader takes as input an integer value +* telling which texture and blending mode to use among a set of +* predefined textures. +* Here are the different presets: +* 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM +* 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM +* 2) -> /brushes/oil.bmp, HUMID_MEDIUM +* 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM +* 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM +* 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM +* 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM +* 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM +* Any other value will lead to the following preset: +* default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM. +*/ +class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME +{ +private: + int _textureId; + +public: + /*! Builds the shader. + * \param id + * The number of the preset to use. + */ + TextureAssignerShader(int id) : StrokeShader() + { + _textureId = id; + } + + virtual string getName() const + { + return "TextureAssignerShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; +}; + +/*! [ Texture Shader ]. +* Assigns a texture and a blending mode to the stroke +* in order to simulate its marks system. +*/ +class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader +{ +private: + string _texturePath; + Stroke::MediumType _mediumType; + bool _tips; // 0 or 1 + +public: + /*! Builds the shader from the texture file name and the blending mode to use. + * \param textureFile + * The the texture file name. + * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes directory. + * \param mediumType + * The medium type and therefore, the blending mode that must be used for the rendering of this stroke. + * \param iTips + * Tells whether the texture includes tips or not. + * If it is the case, the texture image must respect the following format: + * \verbatim + * __________ + * | | + * | A | + * |__________| + * | | | + * | B | C | + * |_____|____| + * + * \endverbatim + * - A : The stroke's corpus texture + * - B : The stroke's left extremity texture + * - C : The stroke's right extremity texture + */ + StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, + bool iTips = false) + : StrokeShader() + { + _texturePath = textureFile; + _mediumType = mediumType; + _tips = iTips; + } + + virtual string getName() const + { + return "StrokeTextureShader"; + } + + /*! The shading method */ + virtual int shade(Stroke& stroke) const; +}; + + // -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// Geometry Shaders // /////////////////////////////////////////////////////////////////////////////// +/*! [ 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 LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader +{ +private: + float _amount; + +public: + /*! Builds the shader. + * \param iAmount + * The stretching amount value. + */ + BackboneStretcherShader(float iAmount = 2.0f) : StrokeShader() + { + _amount = iAmount; + } -#ifndef BASIC_STROKE_SHADERS_H -# define BASIC_STROKE_SHADERS_H + virtual string getName() const + { + return "BackboneStretcherShader"; + } -# include "Stroke.h" -# include "../geometry/Geom.h" -# include "../geometry/Bezier.h" -# include "StrokeShader.h" -# include + /*! The shading method */ + virtual int shade(Stroke& stroke) const; +}; + +/*! [ Geometry Shader. ] + * Resamples the stroke. + * @see Stroke::Resample(float). + */ +class LIB_STROKE_EXPORT 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; + } -using namespace std; -using namespace Geometry; + virtual string getName() const + { + return "SamplingShader"; + } -namespace StrokeShaders { + /*! The shading method */ + virtual int shade(Stroke& stroke) const; +}; + + +class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader +{ +private: + float _amount; + +public: + ExternalContourStretcherShader(float iAmount = 2.0f) : StrokeShader() + { + _amount = iAmount; + } + + virtual string getName() const + { + return "ExternalContourStretcherShader"; + } + + virtual int shade(Stroke& stroke) const; +}; + +// B-Spline stroke shader +class LIB_STROKE_EXPORT BSplineShader: public StrokeShader +{ +public: + BSplineShader() : StrokeShader() {} + + virtual string getName() const + { + return "BSplineShader"; + } + + 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 bezier/bezier.html \endhtmlonly + */ +class LIB_STROKE_EXPORT 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; +}; + +/* Shader to inflate the curves. It keeps the extreme points positions and moves the other ones along the 2D normal. + * The displacement value is proportional to the 2d curvature at the considered point (the higher the curvature, + * the smaller the displacement) and to a value specified by the user. + */ +class LIB_STROKE_EXPORT InflateShader : public StrokeShader +{ +private: + float _amount; + float _curvatureThreshold; + +public: + /*! Builds an inflate shader + * \param iAmount + * A multiplicative coefficient that acts on the amount and direction of displacement + * \param iThreshold + * The curves having a 2d curvature > iThreshold at one of their points is not inflated + */ + InflateShader(float iAmount, float iThreshold) : StrokeShader() + { + _amount = iAmount; + _curvatureThreshold = iThreshold; + } + + virtual string getName() const + { + return "InflateShader"; + } + + /*! 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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; +}; + +/*! [ output Shader ]. + * streams the Stroke + */ +class LIB_STROKE_EXPORT streamShader : public StrokeShader +{ +public: + /*! Destructor. */ + virtual ~streamShader() {} + + /*! Returns the string "streamShader".*/ + virtual string getName() const + { + return "streamShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; +}; + +/*! [ output Shader ]. + * streams the Stroke in a file + */ +class LIB_STROKE_EXPORT fstreamShader : public StrokeShader +{ +protected: + mutable ofstream _stream; + +public: + /*! Builds the shader from the output file name */ + fstreamShader(const char *iFileName) : StrokeShader() + { + _stream .open(iFileName); + if (!_stream.is_open()) { + cout << "couldn't open file " << iFileName << endl; + } + } + + /*! Destructor. */ + virtual ~fstreamShader() + { + _stream.close(); + } + + /*! Returns the string "fstreamShader".*/ + virtual string getName() const + { + return "fstreamShader"; + } + + /*! The shading method. */ + virtual int shade(Stroke& stroke) const; +}; - // - // Thickness modifiers - // - ////////////////////////////////////////////////////// - /*! [ Thickness Shader ]. - * Assigns an absolute constant thickness to every - * vertices of the Stroke. - */ - class LIB_STROKE_EXPORT 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 ]. - * Assigns an absolute constant external thickness to every - * vertices of the Stroke. The external thickness of a point - * is its thickness from the point to the strip border - * in the direction pointing outside the object the - * Stroke delimitates. - */ - class LIB_STROKE_EXPORT 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 ]. - * Assigns thicknesses values such as the thickness - * increases from a thickness value A to a thickness value B - * between the first vertex to the midpoint vertex and - * then decreases from B to a A between this midpoint vertex - * and the last vertex. - * The thickness is linearly interpolated from A to B. - */ - class LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 ]. - * Applys a pattern (texture) to vary thickness. - * The new thicknesses are the result of the multiplication - * of the pattern and the original thickness - */ - class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader - { - public: - - /*! Builds the shader. - * \param pattern_name - * The texture file name. - * \param iMinThickness - * The minimum thickness we don't want to exceed. - * \param iMaxThickness - * The maximum thickness we don't want to exceed. - * \param stretch - * Tells whether the pattern texture must - * be stretched or repeted to fit the stroke. - */ - ThicknessVariationPatternShader(const string pattern_name, - float iMinThickness = 1.f, - float iMaxThickness = 5.f, - bool stretch = true); - /*! Destructor.*/ - virtual ~ThicknessVariationPatternShader() - { - if(0 != _aThickness) - { - delete [] _aThickness; - _aThickness = 0; - } - } - - virtual string getName() const { - return "ThicknessVariationPatternShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - - private: - - float* _aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1) - unsigned _size; - float _minThickness; - float _maxThickness; - bool _stretch; - }; - - /*! [ Thickness Shader ]. - * Adds some noise to the stroke thickness. - * \see \htmlonly noise/noise.html\endhtmlonly - */ - class LIB_STROKE_EXPORT 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 - // - ///////////////////////////////////////////////////////// - /*! [ Color Shader ]. - * Assigns a constant color to every vertices of the Stroke. - */ - class LIB_STROKE_EXPORT 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.f) - : 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 ]. - * Assigns a varying color to the stroke. - * 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 LIB_STROKE_EXPORT 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 ]. - * Applys a pattern to vary original color. - * The new color is the result of the multiplication - * of the pattern and the original color - */ - class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader - { - public: - /*! Builds the shader from the pattern texture file name. - * \param pattern_name - * The file name of the texture file to use as pattern - * \param stretch - * Tells whether the texture must be strecthed or repeted - * to fit the stroke. - */ - ColorVariationPatternShader(const string pattern_name, bool stretch = true); - /*! Destructor */ - virtual ~ColorVariationPatternShader() - { - if(0 != _aVariation) - { - delete [] _aVariation; - _aVariation = 0; - } - } - - virtual string getName() const { - return "ColorVariationPatternShader"; - } - - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - - private: - - float* _aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1) - unsigned _size; - bool _stretch; - }; - - /* [ Color Shader ]. - * Assigns a color to the stroke depending - * on the material of the shape to which ot belongs - * to. (Disney shader) - */ - class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader - { - private: - float _coefficient; - public: - MaterialColorShader(float coeff=1.f) - : StrokeShader() - {_coefficient=coeff;} - - virtual string getName() const { - return "MaterialColorShader"; - } - - virtual int shade(Stroke& stroke) const; - }; - - class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader - { - private: - int _textureId; - Vec2d _orientation; - public: - CalligraphicColorShader( - const Vec2d &iOrientation) - : StrokeShader() - { - _orientation=iOrientation; - _orientation.normalize(); - } - - virtual string getName() const { - return "CalligraphicColorShader"; - } - - virtual int shade(Stroke& stroke) const; - - }; - - /*! [ Color Shader ]. - * Shader to add noise to the stroke colors. - */ - class LIB_STROKE_EXPORT 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; - }; - - // - // Texture Shaders - // - /////////////////////////////////////////////////////////////////////////////// - /*! [ Texture Shader ]. - * Assigns a texture to the stroke in order to simulate - * its marks system. This shader takes as input an integer value - * telling which texture and blending mode to use among a set of - * predefined textures. - * Here are the different presets: - * 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM - * 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM - * 2) -> /brushes/oil.bmp, HUMID_MEDIUM - * 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM - * 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM - * 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM - * 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM - * 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM - * Any other value will lead to the following preset: - * default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM. - */ - class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME - { - private: - int _textureId; - public: - /*! Builds the shader. - * \param id - * The number of the preset to use. - */ - TextureAssignerShader(int id) - : StrokeShader() - { - _textureId = id; - } - - virtual string getName() const { - return "TextureAssignerShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; - - }; - /*! [ Texture Shader ]. - * Assigns a texture and a blending mode to the stroke - * in order to simulate its marks system. - */ - class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader - { - private: - string _texturePath; - Stroke::MediumType _mediumType; - bool _tips; // 0 or 1 - - public: - /*! Builds the shader from the texture file name and the blending mode to use. - * \param textureFile - * The the texture file name. - * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes - * directory. - * \param mediumType - * The medium type and therefore, the blending mode that must - * be used for the rendering of this stroke. - * \param iTips - * Tells whether the texture includes tips or not. - * If it is the case, the texture image must respect the following - * format: - * \verbatim - * __________ - * | | - * | A | - * |__________| - * | | | - * | B | C | - * |_____|____| - * - * \endverbatim - * - A : The stroke's corpus texture - * - B : The stroke's left extremity texture - * - C : The stroke's right extremity texture - */ - StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, bool iTips = false) - : StrokeShader() - { - _texturePath = textureFile; - _mediumType = mediumType; - _tips = iTips; - } - - virtual string getName() const { - return "StrokeTextureShader"; - } - - /*! The shading method */ - virtual int shade(Stroke& stroke) const; - - }; - - - // - // Geometry Shaders - // - /////////////////////////////////////////////////////////////////////////////// - /*! [ 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 LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader - { - private: - float _amount; - public: - /*! Builds the shader. - * \param iAmount - * The stretching amount value. - */ - BackboneStretcherShader(float iAmount=2.f) - : 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader - { - private: - float _amount; - public: - ExternalContourStretcherShader(float iAmount=2.f) - : StrokeShader() - { - _amount = iAmount; - } - - virtual string getName() const { - return "ExternalContourStretcherShader"; - } - - virtual int shade(Stroke& stroke) const; - }; - - // B-Spline stroke shader - class LIB_STROKE_EXPORT BSplineShader: public StrokeShader - { - public: - BSplineShader() - : StrokeShader() - {} - - virtual string getName() const { - return "BSplineShader"; - } - - 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 bezier/bezier.html \endhtmlonly - */ - class LIB_STROKE_EXPORT 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; - }; - - /* Shader to inflate the curves. It keeps the extreme - * points positions and moves the other ones along - * the 2D normal. The displacement value is proportional - * to the 2d curvature at the considered point (the higher - * the curvature, the smaller the displacement) and to a value - * specified by the user. - */ - class LIB_STROKE_EXPORT InflateShader : public StrokeShader - { - private: - float _amount; - float _curvatureThreshold; - public: - /*! Builds an inflate shader - * \param iAmount - * A multiplicative coefficient that - * acts on the amount and direction of displacement - * \param iThreshold - * The curves having a 2d curvature > iThreshold - * at one of their points is not inflated - */ - InflateShader(float iAmount,float iThreshold) - : StrokeShader() - { - _amount = iAmount; - _curvatureThreshold = iThreshold; - } - - virtual string getName() const { - return "InflateShader"; - } - - /*! 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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; - }; - - /*! [ output Shader ]. - * streams the Stroke - */ - class LIB_STROKE_EXPORT streamShader : public StrokeShader - { - public: - /*! Destructor. */ - virtual ~streamShader() {} - /*! Returns the string "streamShader".*/ - virtual string getName() const { - return "streamShader"; - } - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - }; - - /*! [ output Shader ]. - * streams the Stroke in a file - */ - class LIB_STROKE_EXPORT fstreamShader : public StrokeShader - { - protected: - mutable ofstream _stream; - public: - /*! Builds the shader from the output file name */ - fstreamShader(const char *iFileName) : StrokeShader(){ - _stream .open(iFileName); - if(!_stream.is_open()){ - cout << "couldn't open file " << iFileName << endl; - } - } - /*! Destructor. */ - virtual ~fstreamShader() {_stream.close();} - /*! Returns the string "fstreamShader".*/ - virtual string getName() const { - return "fstreamShader"; - } - /*! The shading method. */ - virtual int shade(Stroke& stroke) const; - }; } // end of namespace StrokeShaders -#endif // 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 f2cfe6a855f..a51c138f64e 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -1,455 +1,471 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "StrokeRenderer.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/Canvas.cpp + * \ingroup freestyle + * \brief Class to define a canvas designed to draw style modules + * \author Stephane Grabli + * \date 20/10/2002 + */ + +#include #include -#include "../system/FreestyleConfig.h" -#include "../system/TimeStamp.h" -#include "../system/PseudoNoise.h" + #include "Canvas.h" +#include "StrokeRenderer.h" +#include "StyleModule.h" + #include "../image/Image.h" #include "../image/GaussianFilter.h" #include "../image/ImagePyramid.h" + +#include "../system/FreestyleConfig.h" +#include "../system/TimeStamp.h" +#include "../system/PseudoNoise.h" + #include "../view_map/SteerableViewMap.h" -#include "StyleModule.h" //soc #include //soc #include -#include extern "C" { -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" +# include "IMB_imbuf.h" +# include "IMB_imbuf_types.h" } using namespace std; LIB_STROKE_EXPORT -Canvas * Canvas::_pInstance = 0; +Canvas *Canvas::_pInstance = 0; LIB_STROKE_EXPORT -const char * Canvas::_MapsPath = 0; - -using namespace std; +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) { - _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::Draw() { - if(_StyleModules.empty()) - return; - preDraw(); - TimeStamp *timestamp = TimeStamp::instance(); + if (_StyleModules.empty()) + return; + preDraw(); + TimeStamp *timestamp = TimeStamp::instance(); - for(unsigned 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::iterator sl=_Layers.begin(), slend=_Layers.end(); - sl != slend; - ++sl) - if (*sl) - delete (*sl); - _Layers.clear(); - } - - if(!_StyleModules.empty()) { - for (deque::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s != send; - ++s) - if (*s) - delete (*s); - _StyleModules.clear(); - } - if(_steerableViewMap) - _steerableViewMap->Reset(); + if (!_Layers.empty()) { + for (deque::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) { + if (*sl) + delete (*sl); + } + _Layers.clear(); + } + + if (!_StyleModules.empty()) { + for (deque::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::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::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); +void Canvas::PushBackStyleModule(StyleModule *iStyleModule) +{ + 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; - } +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); + _Layers.insert(_Layers.begin() + index, layer); } void Canvas::RemoveStyleModule(unsigned index) { - unsigned i=0; - if (!_StyleModules.empty()) - { - for(deque::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s!=send; - ++s) - { - if(i == index) - { - // remove shader - if (*s) - delete *s; - _StyleModules.erase(s); - break; - } - ++i; + unsigned int i = 0; + if (!_StyleModules.empty()) { + for (deque::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::iterator sl = _Layers.begin(), slend = _Layers.end(); + sl != slend; + ++sl, ++i) + { + if (i == index) { + // remove layer + if (*sl) + delete *sl; + _Layers.erase(sl); + break; + } + } } - } - i=0; - if(!_Layers.empty()) - { - for(deque::iterator sl=_Layers.begin(), slend=_Layers.end(); - sl!=slend; - ++sl) - { - if(i == index) - { - // remove layer - if (*sl) - delete *sl; - _Layers.erase(sl); - break; - } - ++i; - } - } } 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::iterator s=_StyleModules.begin(), send=_StyleModules.end(); - s != send; - ++s) - { - if(i == index) - { - if (*s) - delete *s; - *s = iStyleModule; - break; + unsigned i = 0; + for (deque::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s, ++i) { + if (i == index) { + if (*s) + delete *s; + *s = iStyleModule; + break; + } } - ++i; - } } -void Canvas::setVisible(unsigned index, bool iVisible) { - _StyleModules[index]->setDisplayed(iVisible); +void Canvas::setVisible(unsigned index, bool 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 size = _StyleModules.size(); - for(unsigned 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& vec, unsigned index) { - unsigned size = _StyleModules.size(); +void Canvas::causalStyleModules(vector& vec, unsigned index) +{ + unsigned int size = _StyleModules.size(); - for(unsigned 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 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 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){ - // 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; - } - - //soc - // QImage *qimg; - // QImage newMap(filePath.c_str()); - // if(newMap.isNull()){ - // cout << "Could not load image file " << filePath << endl; - // return; - // } - // qimg = &newMap; +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()) { + cout << "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 ){ + ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL); + if (qimg == 0) { cout << "Could not load image file " << filePath << endl; - return; + return; } - // soc - //resize - // QImage scaledImg; - // if((newMap.width()!=width()) || (newMap.height()!=height())){ - // scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - // qimg = &scaledImg; - // } +#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()); - } - - - // deal with color image - // if(newMap->depth() != 8){ - // int w = newMap->width(); - // int h = newMap->height(); - // QImage *tmp = new QImage(w, h, 8); - // for(unsigned y=0;ypixel(x,y)); - // tmp->setPixel(x,y,c); - // } - // } - // delete newMap; - // newMap = tmp; - // } - - int x,y; - int w = qimg->x; - int h = qimg->y; -int rowbytes = w*4; - GrayImage tmp(w,h); - char *pix; - - for(y=0; yrect + y*rowbytes + x*4; - float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32; - tmp.setPixel(x,y,c); - } - } - - // GrayImage blur(w,h); - // GaussianFilter gf(4.f); - // //int bound = gf.getBound(); - // for(y=0; y(&tmp, x,y); - // blur.setPixel(x,y,c); - // } - // } - - 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; igetNumberOfLevels(); ++i){ - // save each image: - // w = pyramid.width(i); - // h = pyramid.height(i); - - //soc QImage qtmp(ow, oh, QImage::Format_RGB32); - ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect); - -//int k = (1<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= BMP; - IMB_saveiff(qtmp, const_cast(filename.str().c_str()), 0); - - } - // QImage *qtmp = new QImage(w, h, 32); - // for(y=0;ysetPixel(x,y,qRgb(c,c,c)); - // } - // } - // delete newMap; - // newMap = qtmp; - // - _maps[iMapName] = pyramid; - // newMap->save("toto.bmp", "BMP"); + if ((qimg->x != width()) || (qimg->y != height())) { + scaledImg = IMB_dupImBuf(qimg); + IMB_scaleImBuf(scaledImg, width(), height()); + } + + + // 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; + } +#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); + } + } + +#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(&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: +#if 0 + 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 = BMP; + IMB_saveiff(qtmp, const_cast(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; +#endif + + _maps[iMapName] = pyramid; + //newMap->save("toto.bmp", "BMP"); } -float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){ - if(_maps.empty()){ - cout << "readMapPixel warning: no map was loaded "<< endl; - return -1; - } - mapsMap::iterator m = _maps.find(iMapName); - if(m==_maps.end()){ - 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); +float Canvas::readMapPixel(const char *iMapName, int level, int x, int y) +{ + if (_maps.empty()) { + cout << "readMapPixel warning: no map was loaded "<< endl; + return -1; + } + mapsMap::iterator m = _maps.find(iMapName); + if (m == _maps.end()) { + 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); } diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h index 707455c87f6..9931bf3c97e 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.h +++ b/source/blender/freestyle/intern/stroke/Canvas.h @@ -1,52 +1,60 @@ -// -// Filename : Canvas.h -// Author(s) : Stephane Grabli -// Purpose : Class to define a canvas designed to draw style modules -// Date of creation : 20/10/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef CANVAS_H -# define CANVAS_H - -# include -# include -# include -# include -# include "../system/FreestyleConfig.h" -# include "StrokeLayer.h" -# include "../geometry/BBox.h" -# include "../geometry/Geom.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CANVAS_H__ +#define __FREESTYLE_CANVAS_H__ + +/** \file blender/freestyle/intern/stroke/Canvas.h + * \ingroup freestyle + * \brief Class to define a canvas designed to draw style modules + * \author Stephane Grabli + * \date 20/10/2002 + */ + +#include +#include +#include +#include + +#include "StrokeLayer.h" + +#include "../geometry/BBox.h" +#include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" using namespace Geometry; struct ltstr { - bool operator()(const char* s1, const char* s2) const - { - return strcmp(s1, s2) < 0; - } + bool operator()(const char* s1, const char* s2) const + { + return strcmp(s1, s2) < 0; + } }; class InformationMap; @@ -64,133 +72,178 @@ class StyleModule; /*! Class to define the canvas on which strokes are drawn. * It's used to store state information about the drawing. */ -class LIB_STROKE_EXPORT Canvas +class LIB_STROKE_EXPORT Canvas { public: - /*! Returns a pointer on the Canvas instance */ - static Canvas * getInstance() {return _pInstance;} - typedef std::map mapsMap ; - static const int NB_STEERABLE_VIEWMAP = 5; + /*! Returns a pointer on the Canvas instance */ + static Canvas *getInstance() + { + return _pInstance; + } + + typedef std::map mapsMap; + static const int NB_STEERABLE_VIEWMAP = 5; + protected: - static Canvas *_pInstance; - std::deque _Layers; - std::deque _StyleModules; - FEdge *_SelectedFEdge; - - StrokeRenderer *_Renderer; - StyleModule* _current_sm; - mapsMap _maps; - static const char * _MapsPath; - SteerableViewMap *_steerableViewMap; - bool _basic; + static Canvas *_pInstance; + std::deque _Layers; + std::deque _StyleModules; + FEdge *_SelectedFEdge; + + StrokeRenderer *_Renderer; + StyleModule *_current_sm; + mapsMap _maps; + static const char *_MapsPath; + SteerableViewMap *_steerableViewMap; + bool _basic; 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.f); - - /*! 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 scene3DBBox() const = 0; - inline const StrokeRenderer * renderer() const {return _Renderer;} - inline StyleModule* getCurrentStyleModule() { return _current_sm; } - virtual bool getRecordFlag() const {return false;} + /* 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 scene3DBBox() const = 0; + + inline const StrokeRenderer *renderer() const + { + return _Renderer; + } + + inline StyleModule *getCurrentStyleModule() + { + return _current_sm; + } + + virtual bool getRecordFlag() const + { + return false; + } + int 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) ; - //inline void setDensityMap(InformationMap* iMap) {_DensityMap = iMap;} - inline void AddLayer(StrokeLayer *iLayer) {_Layers.push_back(iLayer);} - void resetModified(bool iMod=false); - void causalStyleModules(std::vector& vec, unsigned index = 0); - void setModified(unsigned index, bool b); + /*! 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 *iMap) + { + _DensityMap = iMap; + } +#endif + + inline void AddLayer(StrokeLayer *iLayer) + { + _Layers.push_back(iLayer); + } + + void resetModified(bool iMod = false); + void causalStyleModules(std::vector& vec, unsigned index = 0); + void setModified(unsigned index, bool b); }; -#endif // 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 bf61a3b32cb..59cebbd5da0 100644 --- a/source/blender/freestyle/intern/stroke/Chain.cpp +++ b/source/blender/freestyle/intern/stroke/Chain.cpp @@ -1,151 +1,156 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/Chain.h + * \ingroup freestyle + * \brief Class to define a chain of viewedges. + * \author Stephane Grabli + * \date 09/01/2003 + */ #include "Chain.h" -#include "../view_map/ViewMapIterators.h" + #include "../view_map/ViewMapAdvancedIterators.h" +#include "../view_map/ViewMapIterators.h" 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->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->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(); - } - - 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->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 (!_fedgeB) - _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); -} + 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->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 (!_fedgeB) + _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); +} diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h index 0dc3dd21a28..425761d28ef 100644 --- a/source/blender/freestyle/intern/stroke/Chain.h +++ b/source/blender/freestyle/intern/stroke/Chain.h @@ -1,87 +1,116 @@ -// -// Filename : Chain.h -// Author(s) : Stephane Grabli -// Purpose : Class to define a chain of viewedges. -// Date of creation : 09/01/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CHAIN_H__ +#define __FREESTYLE_CHAIN_H__ +/** \file blender/freestyle/intern/stroke/Chain.h + * \ingroup freestyle + * \brief Class to define a chain of viewedges. + * \author Stephane Grabli + * \date 09/01/2003 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include "Curve.h" -#ifndef CHAIN_H -# define CHAIN_H +#include "../view_map/ViewMap.h" -# include "../view_map/ViewMap.h" -# include "Curve.h" -/*! 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 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(). + // 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"; - } + /*! 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); - /*! 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 void setSplittingId(Id * sid){_splittingId = sid;} - inline Id* getSplittingId() {return _splittingId;} + inline Id* getSplittingId() + { + return _splittingId; + } }; -#endif // 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 c54ee6ea1ee..1883e494eab 100644 --- a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp @@ -1,96 +1,120 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/ChainingIterators.cpp + * \ingroup freestyle + * \brief Chaining iterators + * \author Stephane Grabli + * \date 01/07/2003 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// #include "ChainingIterators.h" + #include "../system/TimeStamp.h" -ViewEdge* AdjacencyIterator::operator*() { - return (*_internalIterator).first; +ViewEdge* AdjacencyIterator::operator*() +{ + return (*_internalIterator).first; } -bool AdjacencyIterator::isIncoming() const{ - return (*_internalIterator).second; + +bool AdjacencyIterator::isIncoming() const +{ + return (*_internalIterator).second; } -int AdjacencyIterator::increment(){ - ++_internalIterator; - while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first))) - ++_internalIterator; - return 0; +int AdjacencyIterator::increment() +{ + ++_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; +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; } -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; +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; - } - 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; +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; - } - if (traverse(it) < 0) - return -1; - _edge = result; - if(_edge == 0) - return 0; - if(_edge->B() == vertex) - _orientation = true; - else - _orientation = false; - return 0; } // @@ -98,73 +122,81 @@ int ChainingIterator::decrement() { // /////////////////////////////////////////////////////////// -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, SUGGESTIVE, VALLEY, RIDGE - Nature::EdgeNature natures[6] = {Nature::SILHOUETTE, Nature::BORDER, Nature::CREASE, Nature::SUGGESTIVE_CONTOUR, Nature::VALLEY, Nature::RIDGE}; - for(unsigned i=0; i<6; ++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; - } +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; - } - } - } - 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, SUGGESTIVE, VALLEY, RIDGE + Nature::EdgeNature natures[6] = { + Nature::SILHOUETTE, + Nature::BORDER, + Nature::CREASE, + Nature::SUGGESTIVE_CONTOUR, + Nature::VALLEY, + Nature::RIDGE + }; + for (unsigned int i = 0; i < 6; ++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){ - 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; - } +int ChainPredicateIterator::traverse(const AdjacencyIterator& ait) +{ + 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; } - ++it; - } - result = 0; - return 0; -} + result = 0; + return 0; +} diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h index fec8d5ab6dc..66a57061ec9 100644 --- a/source/blender/freestyle/intern/stroke/ChainingIterators.h +++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h @@ -1,42 +1,51 @@ -// -// Filename : ChainingIterators -// Author : Stephane Grabli -// Purpose : Chaining iterators -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// -#ifndef CHAININGITERATORS_H -# define CHAININGITERATORS_H +#ifndef __FREESTYLE_CHAINING_ITERATORS_H__ +#define __FREESTYLE_CHAINING_ITERATORS_H__ + +/** \file blender/freestyle/intern/stroke/ChainingIterators.h + * \ingroup freestyle + * \brief Chaining iterators + * \author Stephane Grabli + * \date 01/07/2003 + */ + +#include -# include "../view_map/ViewMap.h" -# include "../view_map/ViewMapIterators.h" -# include "../view_map/ViewMapAdvancedIterators.h" -# include -# include "Predicates1D.h" +#include "Predicates1D.h" + +#include "../python/Director.h" #include "../system/Iterator.h" //soc -# include "../python/Director.h" +#include "../view_map/ViewMap.h" +#include "../view_map/ViewMapIterators.h" +#include "../view_map/ViewMapAdvancedIterators.h" //using namespace ViewEdgeInternal; @@ -44,73 +53,95 @@ // Adjacency iterator used in the chaining process // /////////////////////////////////////////////////////////// -class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator { +class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator +{ protected: - ViewVertexInternal::orientedViewEdgeIterator _internalIterator; - bool _restrictToSelection; - bool _restrictToUnvisited; + 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 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; - } + 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 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); + bool isValid(ViewEdge* edge); }; // @@ -119,121 +150,114 @@ protected: /////////////////////////////////////////////////////////// /*! Base class for chaining iterators. - * This class is designed to be overloaded - * in order to describe chaining rules. - * It makes the works of chaining rules description - * easier. - * The two main methods that need to overloaded are - * traverse() and init(). + * This class is designed to be overloaded in order to describe chaining rules. + * It makes the works of chaining rules description easier. + * The two main methods that need to overloaded are traverse() and init(). * traverse() tells which ViewEdge to follow, among the adjacent ones. - * If you specify restriction rules (such as "Chain only - * ViewEdges of the selection"), they will be included - * in the adjacency iterator. (i.e, the adjacent iterator - * will only stop on "valid" edges). + * 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 LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator{ +class LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator +{ protected: - bool _restrictToSelection; - bool _restrictToUnvisited; - bool _increment; //true if we're currently incrementing, false when decrementing - + bool _restrictToSelection; + bool _restrictToUnvisited; + bool _increment; //true if we're currently incrementing, false when decrementing + public: - ViewEdge *result; PyObject *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 = 0, bool orientation = true) - : ViewEdgeIterator(begin, orientation) { - _restrictToSelection = iRestrictToSelection; - _restrictToUnvisited = iRestrictToUnvisited; - _increment = true; - py_c_it = 0; - } - - /*! 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() { - return Director_BPy_ChainingIterator_init( this ); - } - - /*! 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){ - return Director_BPy_ChainingIterator_traverse( this, const_cast(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() ; + + /*! 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 = 0, + bool orientation = true) + : ViewEdgeIterator(begin, orientation) + { + _restrictToSelection = iRestrictToSelection; + _restrictToUnvisited = iRestrictToUnvisited; + _increment = true; + py_c_it = 0; + } + + /*! 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() + { + return Director_BPy_ChainingIterator_init(this); + } + + /*! 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) + { + return Director_BPy_ChainingIterator_traverse(this, const_cast(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(); }; // @@ -243,51 +267,46 @@ public: /*! A ViewEdge Iterator used to follow ViewEdges the most naturally. * For example, it will follow visible ViewEdges of same nature. - * As soon, as the nature or the visibility changes, the iteration - * stops (by setting the pointed ViewEdge to 0). - * In the case of an iteration over a set of ViewEdge that are both - * Silhouette and Crease, there will be a precedence of the silhouette - * over the crease criterion. + * As soon, as the nature or the visibility changes, the iteration stops (by setting the pointed ViewEdge to 0). + * In the case of an iteration over a set of ViewEdge that are both Silhouette and Crease, there will be a precedence + * of the silhouette over the crease criterion. */ class LIB_STROKE_EXPORT 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); + /*! 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; - } + virtual int init() + { + return 0; + } }; // @@ -295,100 +314,94 @@ public: // /////////////////////////////////////////////////////////// -/*! A "generic" user-controlled ViewEdge iterator. This iterator - * is in particular built from a unary predicate and a binary predicate. - * First, the unary predicate is evaluated for all potential next ViewEdges - * in order to only keep the ones respecting a certain constraint. - * Then, the binary predicate is evaluated on the current ViewEdge - * together with each ViewEdge of the previous selection. The first - * ViewEdge respecting both the unary predicate and the binary predicate - * is kept as the next one. If none of the potential next ViewEdge respects - * these 2 predicates, 0 is returned. +/*! A "generic" user-controlled ViewEdge iterator. This iterator is in particular built from a unary predicate and + * a binary predicate. + * First, the unary predicate is evaluated for all potential next ViewEdges in order to only keep the ones respecting + * a certain constraint. + * Then, the binary predicate is evaluated on the current ViewEdge together with each ViewEdge of the previous + * selection. The first ViewEdge respecting both the unary predicate and the binary predicate is kept as the next one. + * If none of the potential next ViewEdge respects these 2 predicates, 0 is returned. */ class LIB_STROKE_EXPORT 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); + 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 - /*! Inits the iterator context */ - virtual int init() { - return 0; - } - +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; + } }; -#endif // CHAININGITERATORS_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 b55da1fb0f8..7723c57921d 100644 --- a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp @@ -1,60 +1,87 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/ContextFunctions.cpp + * \ingroup freestyle + * \brief Functions related to context queries + * \brief Interface to access the context related information. + * \author Stephane Grabli + * \date 20/12/2003 + */ #include "ContextFunctions.h" + #include "../view_map/SteerableViewMap.h" + #include "../system/TimeStamp.h" + namespace ContextFunctions { - - unsigned GetTimeStampCF(){ - return TimeStamp::instance()->getTimeStamp(); - } - - unsigned GetCanvasWidthCF(){ - return Canvas::getInstance()->width(); - } - - unsigned GetCanvasHeightCF(){ - return Canvas::getInstance()->height(); - } - void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float 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); - } - - float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned 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); - } - - FEdge * GetSelectedFEdgeCF(){ - return Canvas::getInstance()->selectedFEdge(); - } + +unsigned GetTimeStampCF() +{ + return TimeStamp::instance()->getTimeStamp(); +} + +unsigned GetCanvasWidthCF() +{ + return Canvas::getInstance()->width(); +} + +unsigned GetCanvasHeightCF() +{ + return Canvas::getInstance()->height(); +} + +void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float 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); +} + +float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned 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); +} + +FEdge * GetSelectedFEdgeCF() +{ + return Canvas::getInstance()->selectedFEdge(); +} + +} // ContextFunctions namespace diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h index 37c98656fa7..0718ebb1d6a 100644 --- a/source/blender/freestyle/intern/stroke/ContextFunctions.h +++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h @@ -1,43 +1,46 @@ -// -// Filename : AdvancedFunctions0D.h -// Author(s) : Stephane Grabli -// Purpose : Functions related to context queries -// Date of creation : 20/12/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_CONTEXT_FUNCTIONS_H__ +#define __FREESTYLE_CONTEXT_FUNCTIONS_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/ContextFunctions.h + * \ingroup freestyle + * \brief Functions related to context queries + * \brief Interface to access the context related information. + * \author Stephane Grabli + * \date 20/12/2003 + */ -#ifndef CONTEXT_FUNCTIONS_HPP -# define CONTEXT_FUNCTIONS_HPP +#include "Canvas.h" -# include "Canvas.h" -# include "../image/Image.h" -# include "../image/GaussianFilter.h" +#include "../image/GaussianFilter.h" +#include "../image/Image.h" -/*! \file ContextFunctions.h - * Interface to access the context related - * information. - */ // // Context Functions definitions // @@ -45,80 +48,73 @@ /*! namespace containing all the Context related functions */ namespace ContextFunctions { - // GetTimeStamp - LIB_STROKE_EXPORT - /*! Returns the system time stamp */ - unsigned GetTimeStampCF(); +// GetTimeStamp +/*! Returns the system time stamp */ +LIB_STROKE_EXPORT +unsigned GetTimeStampCF(); + +// GetCanvasWidth +/*! Returns the canvas width */ +LIB_STROKE_EXPORT +unsigned GetCanvasWidthCF(); + +// GetCanvasHeight +/*! Returns the canvas width */ +LIB_STROKE_EXPORT +unsigned GetCanvasHeightCF(); - // GetCanvasWidth - /*! Returns the canvas width */ - LIB_STROKE_EXPORT - unsigned GetCanvasWidthCF(); - - // GetCanvasHeight - /*! Returns the canvas width */ - LIB_STROKE_EXPORT - unsigned GetCanvasHeightCF(); - - // Load map - /*! Loads an image map for further reading */ - LIB_STROKE_EXPORT - void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma=1.f); +// Load map +/*! Loads an image map for further reading */ +LIB_STROKE_EXPORT +void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels = 4, float iSigma = 1.0f); - // ReadMapPixel - /*! Reads a pixel in a user-defined map - * \return the floating value stored for that pixel - * \param iMapName - * The name of the map - * \param level - * The level of the pyramid in which we wish to read the pixel - * \param x - * The x-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - * \param y - * The y-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - */ - LIB_STROKE_EXPORT - float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y); +// ReadMapPixel +/*! Reads a pixel in a user-defined map + * \return the floating value stored for that pixel + * \param iMapName + * The name of the map + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + */ +LIB_STROKE_EXPORT +float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y); - // ReadCompleteViewMapPixel - /*! Reads a pixel in the complete view map - * \return the floating value stored for that pixel - * \param level - * The level of the pyramid in which we wish to read the pixel - * \param x - * The x-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - * \param y - * The y-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - */ - LIB_STROKE_EXPORT - float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y); +// ReadCompleteViewMapPixel +/*! Reads a pixel in the complete view map + * \return the floating value stored for that pixel + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + */ +LIB_STROKE_EXPORT +float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y); - // ReadOrientedViewMapPixel - /*! Reads a pixel in one of the oriented view map images - * \return the floating value stored for that pixel - * \param iOrientation - * The number telling which orientation we want to check - * \param level - * The level of the pyramid in which we wish to read the pixel - * \param x - * The x-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - * \param y - * The y-coordinate of the pixel we wish to read. The origin is - * in the lower-left corner. - */ - LIB_STROKE_EXPORT - float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y); +// ReadOrientedViewMapPixel +/*! Reads a pixel in one of the oriented view map images + * \return the floating value stored for that pixel + * \param iOrientation + * The number telling which orientation we want to check + * \param level + * The level of the pyramid in which we wish to read the pixel + * \param x + * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + * \param y + * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner. + */ +LIB_STROKE_EXPORT +float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y); - // DEBUG - LIB_STROKE_EXPORT - FEdge * GetSelectedFEdgeCF(); +// DEBUG +LIB_STROKE_EXPORT +FEdge *GetSelectedFEdgeCF(); } // end of namespace ContextFunctions -#endif // CONTEXT_FUNCTIONS_HPP - +#endif // __FREESTYLE_CONTEXT_FUNCTIONS_H__ diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp index 4cca210161e..54b8eeaef36 100644 --- a/source/blender/freestyle/intern/stroke/Curve.cpp +++ b/source/blender/freestyle/intern/stroke/Curve.cpp @@ -1,863 +1,925 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/Curve.cpp + * \ingroup freestyle + * \brief Class to define a container for curves + * \author Stephane Grabli + * \date 11/01/2003 + */ #include "Curve.h" -#include "CurveIterators.h" #include "CurveAdvancedIterators.h" +#include "CurveIterators.h" - /**********************************/ - /* */ - /* */ - /* CurvePoint */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* CurvePoint */ +/* */ +/* */ +/**********************************/ CurvePoint::CurvePoint() { - __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.f)) - { - _Point2d=__B->point2d(); - _Point3d=__B->point3d(); - } - else if((iB == 0) && (t == 0.f)) - { - _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()) - { + __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()); + } +} + +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()) - { + 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()) - { + 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.f) && (iB->t2d() == 0.f)) - { - __A = iA->A(); - __B = iA->B(); - _t2d=t1+t3-t1*t3; - //_t2d = t3; - } - else if((iA->t2d() == 1.f) && (iB->t2d() != 0.f)) - { - __A = iB->A(); - __B = iB->B(); - //_t2d = t3; - _t2d=t2*t3; - } - else if((iA->getPoint2D() - iA->getPoint2D()).norm() < 1e-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() < 1e-6) - { - goto iA_A_eq_iB_A; - } - else if(iA->B() != 0 && iB->B() != 0 && (iA->B()->point3d() - iB->B()->point3d()).norm() < 1e-6) - { - goto iA_B_eq_iB_B; - } - else if(iA->B() != 0 && iB->A() != 0 && (iA->B()->point3d() - iB->A()->point3d()).norm() < 1e-6) - { - goto iA_B_eq_iB_A; - } - if (!__A || !__B) { - 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; - } - assert(__A != 0 && __B != 0); - - //_Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->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) -{ - __A=iBrother.__A; - __B=iBrother.__B; - _t2d=iBrother._t2d; - _Point2d=iBrother._Point2d; - _Point3d=iBrother._Point3d; + 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() - iA->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) { + 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; + } + assert(__A != 0 && __B != 0); + +#if 0 + _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()); +} + +CurvePoint::CurvePoint(const CurvePoint& iBrother) +{ + __A = iBrother.__A; + __B = iBrother.__B; + _t2d = iBrother._t2d; + _Point2d = iBrother._Point2d; + _Point3d = iBrother._Point3d; } CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother) { - __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(&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); - } + __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(&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 - 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()); + 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 0; +} + - return 0; +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); } - Vec3r CurvePoint::normal() const +#if 0 +Material CurvePoint::material() 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 (__A == 0) + return __B->material(); + return __A->material(); } +Id CurvePoint::shape_id() const +{ + if (__A == 0) + return __B->shape_id(); + return __A->shape_id(); +} +#endif - // Material CurvePoint::material() const - //{ - // if(__A == 0) - // return __B->material(); - // return __A->material(); - //} +const SShape *CurvePoint::shape() const +{ + if (__A == 0) + return __B->shape(); + return __A->shape(); +} -// Id CurvePoint::shape_id() const -// { -// if(__A == 0) -// return __B->shape_id(); -// return __A->shape_id(); -// } +#if 0 +float CurvePoint::shape_importance() const +{ + if (__A == 0) + return __B->shape_importance(); + return __A->shape_importance(); +} - const SShape * CurvePoint::shape() const +const unsigned CurvePoint::qi() const { - if(__A == 0) - return __B->shape(); - return __A->shape(); + 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(); +} - -// float CurvePoint::shape_importance() const -// { - -// 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(); - //} - - - 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(); -} - - 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(); -} - - 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(); -} - - 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(); -} - - 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(); -} - - const Polygon3r& CurvePoint::occludee() const -{ - if(__A == 0) - return __B->occludee(); - if(__B == 0) - return __A->occludee(); - return __A->getFEdge(*__B)->occludee(); -} - - 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(); -} - - 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; - - return __A->getFEdge(*__B)->z_discontinuity(); -} -// -// float CurvePoint::local_average_depth() const -//{ -// return local_average_depth_function(this); -//} -// -// float CurvePoint::local_depth_variance() const -//{ -// return local_depth_variance_function(this); -//} -// -// real CurvePoint::local_average_density(float sigma) const -//{ -// //return local_average_density(this); -// -// return density_function(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(); -// } -// -// Vec3r CurvePoint::orientation3d() const -// { -// 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);} -// -// Vec3r CurvePoint::curvature2d_as_vector() const -//{ -// // Vec3r edgeA = (_FEdges[0])->orientation2d().normalize(); -// // Vec3r edgeB = (_FEdges[1])->orientation2d().normalize(); -// // return edgeA+edgeB; -// // -// 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 -//{ -// // 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)); -// -// 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()); -} - -Vec2d CurvePoint::directionFredo () const -{ - if(__A == 0) - return __B->directionFredo(); - if(__B == 0) - return __A->directionFredo(); - return ((1-_t2d)*__A->directionFredo()+_t2d*__B->directionFredo()); -} - - /**********************************/ - /* */ - /* */ - /* Curve */ - /* */ - /* */ - /**********************************/ +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(); +} -/* for functions */ +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(); +} + +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(); +} + +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(); +} + +const Polygon3r& CurvePoint::occludee() const +{ + if (__A == 0) + return __B->occludee(); + if (__B == 0) + return __A->occludee(); + return __A->getFEdge(*__B)->occludee(); +} + +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(); +} + +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; + + return __A->getFEdge(*__B)->z_discontinuity(); +} + +#if 0 +float CurvePoint::local_average_depth() const +{ + return local_average_depth_function(this); +} + +float CurvePoint::local_depth_variance() const +{ + return local_depth_variance_function(this); +} + +real CurvePoint::local_average_density(float sigma) const +{ + //return local_average_density(this); + return density_function(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(); +} + +Vec3r CurvePoint::orientation3d() const +{ + 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); +} + +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()); +} + +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()); +} +#endif +real CurvePoint::curvatureFredo() const +{ + 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()); +} + +/**********************************/ +/* */ +/* */ +/* Curve */ +/* */ +/* */ +/**********************************/ + +/* for functions */ 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) +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.f, 0.f); - //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); + 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 + +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.f, 0.f); - //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); + 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) + +Curve::point_iterator Curve::points_end(float step) { - return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length); - //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _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 + +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.f, _Length); - //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _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);} -Curve::const_point_iterator Curve::vertices_begin() const {return points_begin(0);} -Curve::point_iterator Curve::vertices_end(){return points_end(0);} -Curve::const_point_iterator Curve::vertices_end() const {return points_end(0);} +Curve::point_iterator Curve::vertices_begin() +{ + return points_begin(0); +} + +Curve::const_point_iterator Curve::vertices_begin() const +{ + return points_begin(0); +} + +Curve::point_iterator Curve::vertices_end() +{ + return points_end(0); +} + +Curve::const_point_iterator Curve::vertices_end() const +{ + 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.f, 0.f); -} - -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.f, _Length); -} - -CurveInternal::CurvePointIterator Curve::curveVerticesBegin(){ - return curvePointsBegin(0); -} - -CurveInternal::CurvePointIterator Curve::curveVerticesEnd(){ - 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.f, 0.f)); - 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.f, _Length)); - return ret; -} - -Interface0DIterator Curve::verticesBegin(){ - return pointsBegin(0); -} - -Interface0DIterator Curve::verticesEnd(){ - return pointsEnd(0); -} - - -// Vec3r shaded_color(int iCombination = 0) const ; -// -// Vec3r Curve::orientation2d(point_iterator it) const -//{ -// return (*it)->orientation2d(); -//} -/* template */ -/* Vec3r Curve::orientation2d(int iCombination) const */ -/* { */ -/* return edge_orientation2d_function(this, iCombination); */ -/* } */ -// -// Vec3r Curve::orientation3d(point_iterator it) const -//{ -// return (*it)->orientation3d(); -//} -/* */ -/* Vec3r Curve::orientation3d(int iCombination) const */ -/* { */ -/* return edge_orientation3d_function(this, iCombination); */ -/* } */ -// real curvature2d(point_iterator it) const {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; -//} - -// 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_; -//} -// occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();} -// occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();} - -//int Curve::occluders_size() const -//{ -// 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 Polygon3r& occludee() const {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 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; -//} -/* */ -/* real Curve::z_discontinuity(int iCombination) const */ -/* { */ -/* return z_discontinuity_edge_function(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 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; -//} - - -// occluder_container::const_iterator Curve::occluders_begin() const -//{ -// 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(); -//} - -/* */ -/* Vec3r Curve::curvature2d_as_vector(int iCombination) const */ -/* { */ -/* return curvature2d_as_vector_edge_function(this, iCombination); */ -/* } */ -/* */ -/* real Curve::curvature2d_as_angle(int iCombination) const */ -/* { */ -/* return curvature2d_as_angle_edge_function(this, iCombination); */ -/* } */ - -/* */ -/* float Curve::shape_importance(int iCombination) const */ -/* { */ -/* return shape_importance_edge_function(this, iCombination); */ -/* } */ - -/* */ -/* float Curve::local_average_depth(int iCombination) const */ -/* { */ -/* return local_average_depth_edge_function(this, iCombination); */ -/* } */ -/* */ -/* float Curve::local_depth_variance(int iCombination ) const */ -/* { */ -/* return local_depth_variance_edge_function(this, iCombination); */ -/* // local_depth_variance_functor functor; */ -/* // float result; */ -/* // Evaluate >(&functor, iCombination, result); */ -/* // return result; */ -/* } */ - -/* */ -/* real Curve::local_average_density(float sigma, int iCombination ) const */ -/* { */ -/* return density_edge_function(this, iCombination); */ -/* // density_functor functor; */ -/* // real result; */ -/* // Evaluate >(&functor, iCombination, result); */ -/* // return result; */ -/* } */ +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); +} + +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); +} + +CurveInternal::CurvePointIterator Curve::curveVerticesBegin() +{ + return curvePointsBegin(0); +} + +CurveInternal::CurvePointIterator Curve::curveVerticesEnd() +{ + 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; +} + +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; +} + +Interface0DIterator Curve::verticesBegin() +{ + return pointsBegin(0); +} + +Interface0DIterator Curve::verticesEnd() +{ + return pointsEnd(0); +} + +#if 0 +Vec3r shaded_color(int iCombination = 0) const; + +Vec3r Curve::orientation2d(point_iterator it) const +{ + return (*it)->orientation2d(); +} + +template +Vec3r Curve::orientation2d(int iCombination) const +{ + return edge_orientation2d_function(this, iCombination); +} + +Vec3r Curve::orientation3d(point_iterator it) const +{ + return (*it)->orientation3d(); +} + +Vec3r Curve::orientation3d(int iCombination) const +{ + return edge_orientation3d_function(this, iCombination); +} + +real curvature2d(point_iterator it) const +{ + 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; +} + +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_; +} + +occluder_container::const_iterator occluders_begin() const +{ + return _FEdgeA->occluders().begin(); +} + +occluder_container::const_iterator occluders_end() const +{ + return _FEdgeA->occluders().end(); +} + +int Curve::occluders_size() const +{ + 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 Polygon3r& occludee() const +{ + 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 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; +} +real Curve::z_discontinuity(int iCombination) const +{ + return z_discontinuity_edge_function(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 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; +} + + +occluder_container::const_iterator Curve::occluders_begin() const +{ + const_vertex_iterator v = vertices_begin(); + return (*v)->occluders_begin(); +} -#define EPS_CURVA_DIR 0.01 +occluder_container::const_iterator Curve::occluders_end() const +{ + const_vertex_iterator v = vertices_end(); + return (*v)->occluders_end(); +} + +Vec3r Curve::curvature2d_as_vector(int iCombination) const +{ + return curvature2d_as_vector_edge_function(this, iCombination); +} + +real Curve::curvature2d_as_angle(int iCombination) const +{ + return curvature2d_as_angle_edge_function(this, iCombination); +} + +float Curve::shape_importance(int iCombination) const +{ + return shape_importance_edge_function(this, iCombination); +} + +float Curve::local_average_depth(int iCombination) const +{ + return local_average_depth_edge_function(this, iCombination); +} + +float Curve::local_depth_variance(int iCombination ) const +{ + return local_depth_variance_edge_function(this, iCombination); +#if 0 + local_depth_variance_functor functor; + float result; + Evaluate >(&functor, iCombination, result); + return result; +#endif +} + +real Curve::local_average_density(float sigma, int iCombination ) const +{ + return density_edge_function(this, iCombination); +#if 0 + density_functor functor; + real result; + Evaluate >(&functor, iCombination, result); + return result; +#endif +} +#endif + +#define EPS_CURVA_DIR 0.01 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)setCurvatureFredo((*v)->curvatureFredo()); -// (*vfix)->setDirectionFredo((*v)->directionFredo()); -// } -// } -// isReliable=true; -// vLastReliable=v; -// } -// prevV=v; p0=p1; p1=p2; -// } +#if 0 + 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 60bc9815cb4..f451d83d65b 100644 --- a/source/blender/freestyle/intern/stroke/Curve.h +++ b/source/blender/freestyle/intern/stroke/Curve.h @@ -1,282 +1,364 @@ -// -// Filename : Curve.h -// Author(s) : Stephane Grabli -// Purpose : Class to define a container for curves -// Date of creation : 11/01/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef CURVE_H -# define CURVE_H - -# include "../view_map/Silhouette.h" -# include -# include "../system/BaseIterator.h" -# include "../geometry/Geom.h" -//# include "../scene_graph/FrsMaterial.h" -# include "../view_map/SilhouetteGeomEngine.h" -# include "../view_map/Interface0D.h" -# include "../view_map/Interface1D.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CURVE_H__ +#define __FREESTYLE_CURVE_H__ + +/** \file blender/freestyle/intern/stroke/Curve.h + * \ingroup freestyle + * \brief Class to define a container for curves + * \author Stephane Grabli + * \date 11/01/2003 + */ + +#include + +#include "../geometry/Geom.h" + +//#include "../scene_graph/FrsMaterial.h" + +#include "../view_map/Interface0D.h" +#include "../view_map/Interface1D.h" +#include "../view_map/Silhouette.h" +#include "../view_map/SilhouetteGeomEngine.h" + +#include "../system/BaseIterator.h" using namespace std; using namespace Geometry; - /**********************************/ - /* */ - /* */ - /* CurvePoint */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* CurvePoint */ +/* */ +/* */ +/**********************************/ /*! Class to represent a point of a curve. - * A CurvePoint can be any point of a 1D curve - * (it doesn't have to be a vertex of the curve). - * Any Interface1D is built upon ViewEdges, themselves - * built upon FEdges. Therefore, a curve is basically + * A CurvePoint can be any point of a 1D curve (it doesn't have to be a vertex of the curve). + * Any Interface1D is built upon ViewEdges, themselves built upon FEdges. Therefore, a curve is basically * a polyline made of a list SVertex. - * 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. + * 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 LIB_STROKE_EXPORT 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 Vec3f 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 Vec2f getPoint2D() const { - return Vec2f((float)_Point2d.x(),(float)_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(); - } + /*! 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 Vec3f 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 Vec2f getPoint2D() const + { + return Vec2f((float)_Point2d.x(), (float)_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; + typedef SVertex vertex_type; + protected: - SVertex *__A; - SVertex *__B; - float _t2d; - //float _t3d; - Vec3r _Point2d; - Vec3r _Point3d; + 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;} - //inline const float t3d() const {return _t3d;} - - /* 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;} - //inline void SetT3d(float t) {_t3d = t;} - - /* 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 ; - // 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; + /*! 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; + } +#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; + } + +#if 0 + 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; +#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; +#endif + + real curvatureFredo() const; + Vec2d directionFredo() const; }; - /**********************************/ - /* */ - /* */ - /* Curve */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* Curve */ +/* */ +/* */ +/**********************************/ namespace CurveInternal { - class CurvePoint_const_traits; - class CurvePoint_nonconst_traits; - template class __point_iterator; - class CurvePointIterator; + +class CurvePoint_const_traits; +class CurvePoint_nonconst_traits; +template class __point_iterator; +class CurvePointIterator; + } // end of namespace CurveInternal /*! Base class for curves made of CurvePoints. @@ -286,182 +368,222 @@ namespace CurveInternal { class LIB_STROKE_EXPORT Curve : public Interface1D { public: - typedef CurvePoint Vertex; - typedef CurvePoint Point; - typedef Point point_type; - typedef Vertex vertex_type; - typedef deque vertex_container; - - /* Iterator to iterate over a vertex edges */ - - typedef CurveInternal::__point_iterator point_iterator; - typedef CurveInternal::__point_iterator const_point_iterator; - typedef point_iterator vertex_iterator ; - typedef const_point_iterator const_vertex_iterator ; - + typedef CurvePoint Vertex; + typedef CurvePoint Point; + typedef Point point_type; + typedef Vertex vertex_type; + typedef deque vertex_container; + + /* Iterator to iterate over a vertex edges */ + + typedef CurveInternal::__point_iterator point_iterator; + typedef CurveInternal::__point_iterator 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 + 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"; - } - - /* - fredo's curvature storage - */ - void computeCurvatureAndOrientation (); - - /*! 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 - * oplyline constituing the Curve. - */ - inline unsigned int nSegments() const {return _nSegments;} - - inline void setId(const Id& id){_Id = id;} - /* Information access interface */ - - - //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 ; - - /* 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.f); - CurveInternal::CurvePointIterator curvePointsEnd(float t=0.f); - - 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.f); - /*! 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.f); -}; + /*! 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"; + } + + /* fredo's curvature storage */ + void computeCurvatureAndOrientation(); + + /*! 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 constituing 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; +#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); +}; -#endif +#endif // __FREESTYLE_CURVE_H__ diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h index c1524d18fe1..0c053bf1845 100644 --- a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h +++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h @@ -1,378 +1,383 @@ -// -// Filename : CurveAdvancedIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the elements of the Curve -// Can't be used in python -// Date of creation : 01/08/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef ADVANCEDCURVEITERATORS_H -# define ADVANCEDCURVEITERATORS_H - -# include "Stroke.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__ +#define __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__ + +/** \file blender/freestyle/intern/stroke/CurveAdvancedIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the elements of the Curve. Can't be used in python + * \author Stephane Grabli + * \date 01/08/2003 + */ + +#include "Stroke.h" namespace CurveInternal { - class CurvePoint_const_traits : public Const_traits { - public: - typedef deque vertex_container; - typedef vertex_container::const_iterator vertex_container_iterator; - typedef SVertex vertex_type; - }; - - class CurvePoint_nonconst_traits : public Nonconst_traits { - public: - typedef deque vertex_container; - typedef vertex_container::iterator vertex_container_iterator ; - typedef SVertex vertex_type; - }; - - /**********************************/ - /* */ - /* */ - /* CurvePoint Iterator */ - /* */ - /* */ - /**********************************/ - - - /*! iterator on a curve. Allows an iterating outside - * initial vertices. A CurvePoint is instanciated an returned - * when the iterator is dereferenced. - */ - - template - class __point_iterator : public IteratorBase - { - public: - typedef __point_iterator 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 iterator; - typedef __point_iterator const_iterator; - - // public: - // typedef Vertex vertex_type ; - // typedef vertex_container_iterator vertex_iterator_type; - // typedef CurvePoint Point; - // typedef Point point_type; - typedef IteratorBase parent_class; - //# if defined(__GNUC__) && (__GNUC__ < 3) - // typedef bidirectional_iterator,ptrdiff_t> bidirectional_point_iterator; - //# else - // typedef iterator,ptrdiff_t> bidirectional_point_iterator; - //# endif - friend class Curve; - //friend class Curve::vertex_iterator; - //friend class __point_iterator; - //friend class iterator; - //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: - - public: - inline __point_iterator(float step = 0.f) - : parent_class() - { - _step = step; - _CurvilinearLength = 0.f; - _t = 0.f; - _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.f, float iCurvilinearLength = 0.f) - : 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; - } - inline Self operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - return tmp; - } - inline Self& operator--() // operator corresponding to ++i - { - decrement(); - return *this; - } - inline Self operator--(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - decrement(); // dans un temporaire. - 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*());} - - public: - 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.f)) - { - // we're setting the iterator to end - ++__A; - ++__B; - ++_currentn; - _t = 0.f; - 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.f; - 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.f; // 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.f; - else - { - _t = 0.f; - ++_currentn; - ++__A;++__B; - } - } - } - virtual void decrement() - { - if(_Point != 0) - { - delete _Point; - _Point = 0; - } - - if(_t == 0.f) //we're at the beginning of the edge - { - _t = 1.f; - --_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.f; // We just need a negative value here - - // round value - if(fabs(_t) < (float)M_EPSILON) - _t = 0.0; - if(_t < 0) - { - if(_currentn == 0) - _CurvilinearLength = 0.f; - else - _CurvilinearLength += normAB*(-_t); - _t = 0.f; - } - } - }; - - - -} // end of namespace StrokeInternal - - -#endif // ADVANCEDCURVEITERATORS_H +class CurvePoint_const_traits : public Const_traits +{ +public: + typedef deque vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator; + typedef SVertex vertex_type; +}; + +class CurvePoint_nonconst_traits : public Nonconst_traits +{ +public: + typedef deque vertex_container; + typedef vertex_container::iterator vertex_container_iterator; + typedef SVertex vertex_type; +}; + +/**********************************/ +/* */ +/* */ +/* CurvePoint Iterator */ +/* */ +/* */ +/**********************************/ + + +/*! iterator on a curve. Allows an iterating outside initial vertices. A CurvePoint is instanciated an returned + * when the iterator is dereferenced. + */ +template +class __point_iterator : public IteratorBase +{ +public: + typedef __point_iterator 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 iterator; + typedef __point_iterator const_iterator; + +#if 0 + typedef Vertex vertex_type ; + typedef vertex_container_iterator vertex_iterator_type; + typedef CurvePoint Point; + typedef Point point_type; +#endif + typedef IteratorBase parent_class; +#if 0 +#if defined(__GNUC__) && (__GNUC__ < 3) + typedef bidirectional_iterator, ptrdiff_t> bidirectional_point_iterator; +#else + typedef iterator, ptrdiff_t> bidirectional_point_iterator; +#endif +#endif + friend class Curve; +#if 0 + friend class Curve::vertex_iterator; + friend class __point_iterator; + 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; + } + } +}; + +} // end of namespace CurveInternal + +#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 a45ef4bfdaf..7d9e0e00ef1 100644 --- a/source/blender/freestyle/intern/stroke/CurveIterators.h +++ b/source/blender/freestyle/intern/stroke/CurveIterators.h @@ -1,299 +1,302 @@ -// -// Filename : CurveIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the elements of the Curve -// Date of creation : 01/08/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef CURVEITERATORS_H -# define CURVEITERATORS_H +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CURVE_ITERATORS_H__ +#define __FREESTYLE_CURVE_ITERATORS_H__ + +/** \file blender/freestyle/intern/stroke/CurveIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the elements of the Curve + * \author Stephane Grabli + * \date 01/08/2003 + */ -#include "Stroke.h" #include "Curve.h" +#include "Stroke.h" namespace CurveInternal { - /*! iterator on a curve. Allows an iterating outside - * initial vertices. A CurvePoint is instanciated an returned - * when the iterator is dereferenced. - */ - - class CurvePointIterator : public Interface0DIteratorNested - { - public: - friend class ::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: - - public: - inline CurvePointIterator(float step = 0.f) - : Interface0DIteratorNested() - { - _step = step; - _CurvilinearLength = 0.f; - _t = 0.f; - //_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.f, float iCurvilinearLength = 0.f) - : 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(&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*());} - public: - 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.f)) - { - // we're setting the iterator to end - ++__A; - ++__B; - ++_currentn; - _t = 0.f; - 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.f; - 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.f; // 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.f; - else - { - _t = 0.f; - ++_currentn; - ++__A;++__B; - } - } - return 0; - } - virtual int decrement() - { - if(_t == 0.f) //we're at the beginning of the edge - { - _t = 1.f; - --_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.f; // We just need a negative value here - - // round value - if(fabs(_t) < (float)M_EPSILON) - _t = 0.0; - if(_t < 0) - { - if(_currentn == 0) - _CurvilinearLength = 0.f; - else - _CurvilinearLength += normAB*(-_t); - _t = 0.f; - } - return 0; - } - - virtual float t() const{ - return _CurvilinearLength; - } - virtual float u() const{ - return _CurvilinearLength/_CurveLength; - } - }; - - - -} // end of namespace StrokeInternal - -#endif // CURVEITERATORS_H +/*! iterator on a curve. Allows an iterating outside +* initial vertices. A CurvePoint is instanciated an returned +* when the iterator is dereferenced. +*/ + +class CurvePointIterator : public Interface0DIteratorNested +{ +public: + friend class ::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(&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 + +#endif // __FREESTYLE_CURVE_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h index 21bebebc6f8..daa02002b7b 100644 --- a/source/blender/freestyle/intern/stroke/Modifiers.h +++ b/source/blender/freestyle/intern/stroke/Modifiers.h @@ -1,71 +1,74 @@ -// -// Filename : Modifiers.h -// Author : Stephane Grabli -// Purpose : modifiers... -// Date of creation : 05/01/2003 -// -/////////////////////////////////////////////////////////////////////////////// - +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#ifndef __FREESTYLE_MODIFIERS_H__ +#define __FREESTYLE_MODIFIERS_H__ -#ifndef MODIFIERS_H -# define MODIFIERS_H +/** \file blender/freestyle/intern/stroke/Modifiers.h + * \ingroup freestyle + * \brief modifiers... + * \author Stephane Grabli + * \date 05/01/2003 + */ -# include "TimeStamp.h" +#include "TimeStamp.h" /* ----------------------------------------- * * * - * modifiers * + * modifiers * * * * ----------------------------------------- */ + /*! Base class for modifiers. - * Modifiers are used in the - * Operators in order to "mark" - * the processed Interface1D. + * Modifiers are used in the Operators in order to "mark" the processed Interface1D. */ template -struct EdgeModifier : public unary_function +struct EdgeModifier : public unary_function { - /*! Default construction */ - EdgeModifier() : unary_function() {} - /*! the () operator */ - virtual void operator()(Edge& iEdge) {} + /*! Default construction */ + EdgeModifier() : unary_function() {} + + /*! the () operator */ + virtual void operator()(Edge& iEdge) {} }; -/*! Modifier that sets the time stamp - * of an Interface1D to the time stamp - * of the system. - */ +/*! Modifier that sets the time stamp of an Interface1D to the time stamp of the system. */ template struct TimestampModifier : public EdgeModifier { - /*! Default constructor */ - TimestampModifier() : EdgeModifier() {} - /*! The () operator. */ - virtual void operator()(Edge& iEdge) - { - TimeStamp *timestamp = TimeStamp::instance(); - iEdge.setTimeStamp(timestamp->getTimeStamp()); - } + /*! Default constructor */ + TimestampModifier() : EdgeModifier() {} + + /*! The () operator. */ + virtual void operator()(Edge& iEdge) + { + TimeStamp *timestamp = TimeStamp::instance(); + iEdge.setTimeStamp(timestamp->getTimeStamp()); + } }; #endif // MODIFIERS_H diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h index 591bb157392..da6708e6ea9 100644 --- a/source/blender/freestyle/intern/stroke/Module.h +++ b/source/blender/freestyle/intern/stroke/Module.h @@ -1,72 +1,82 @@ -// -// Filename : Module.h -// Author(s) : Emmanuel Turquin -// Purpose : Set the type of the module -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_MODULE_H__ +#define __FREESTYLE_MODULE_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/Module.h + * \ingroup freestyle + * \brief Set the type of the module + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -#ifndef MODULE_H -# define MODULE_H - -# include "Canvas.h" -# include "StyleModule.h" +#include "Canvas.h" +#include "StyleModule.h" class Module { public: + static void setAlwaysRefresh(bool b = true) + { + getCurrentStyleModule()->setAlwaysRefresh(b); + } - 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(); - } + static StyleModule* getCurrentStyleModule() + { + Canvas *canvas = Canvas::getInstance(); + return canvas->getCurrentStyleModule(); + } }; -#endif // 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 80562e104d2..15aff89db45 100644 --- a/source/blender/freestyle/intern/stroke/Operators.cpp +++ b/source/blender/freestyle/intern/stroke/Operators.cpp @@ -1,643 +1,667 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/Operators.cpp + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "Operators.h" #include #include + +#include "Operators.h" #include "Canvas.h" #include "Stroke.h" -LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set; -LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set; -LIB_STROKE_EXPORT Operators::I1DContainer* Operators::_current_set = NULL; -LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set; - -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; +LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set; +LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set; +LIB_STROKE_EXPORT Operators::I1DContainer *Operators::_current_set = NULL; +LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set; + +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(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 ((*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) { - 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(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain* new_chain = new Chain(id);++id; - for (;;) { - 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; +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(*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; } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { + return 0; + +error: for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); + delete (*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; + return -1; } -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(*it_edge); - it.setBegin(edge); - it.setCurrentEdge(edge); - - Chain* new_chain = new Chain(id);++id; - for (;;) { - 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; +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(*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; } - new_chains_set.push_back(new_chain); - } - - if (!new_chains_set.empty()) { + return 0; + +error: for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); + delete (*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; + return -1; } -//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(*it_edge); -// it.setBegin(edge); -// it.setCurrentEdge(edge); -// -// Chain* new_chain = new Chain(id);++id; -// //ViewEdgeIterator it_back(it);--it_back; // FIXME -// 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(*it_edge); -// it.setBegin(edge); -// it.setCurrentEdge(edge); - // - // Chain* new_chain = new Chain(id);++id; - // //ViewEdgeIterator it_back(it);--it_back;//FIXME - // 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; - //} - -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(*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; - //ViewEdgeIterator it_back(it);--it_back;//FIXME - for (;;) { - 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; +#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(*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); } - 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); + + 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(*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); } - 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; + if (!_current_chains_set.empty()) + _current_set = &_current_chains_set; } +#endif + +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(*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; +#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); + } -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(*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; - //ViewEdgeIterator it_back(it);--it_back;//FIXME - 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; + 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; } - 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()) { + return 0; + +error: for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) { - _current_chains_set.push_back(*it); + delete (*it); } new_chains_set.clear(); - _current_set = &_current_chains_set; - } - return 0; + return -1; +} + +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(*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; +#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; 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(&(*it)); - new_curve->push_vertex_back(point);++it; - for(; it!= end; ++it) - { - point = dynamic_cast(&(*it)); - new_curve->push_vertex_back(point); - if(pred(it) < 0) - { + 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(&(*it)); + new_curve->push_vertex_back(point); + ++it; + for (; it!= end; ++it) { + point = dynamic_cast(&(*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; - 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(); + 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; + 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); } - _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(&(*itStart)); - new_curve->push_vertex_back(point); - do{ - point = dynamic_cast(&(*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(&(*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(&(*itStart)); + new_curve->push_vertex_back(point); + do { + point = dynamic_cast(&(*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(&(*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; + 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); } - _current_chains_set.push_back(*cit); - } #endif - splitted_chains.clear(); - - if (!_current_chains_set.empty()) - _current_set = &_current_chains_set; - return 0; + splitted_chains.clear(); + + 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; } #include "CurveIterators.h" @@ -646,591 +670,608 @@ error: static int __recursiveSplit(Chain *_curve, UnaryFunction0D& 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;++it;//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._CurvilinearLengthpush_vertex_back(&(*vit)); - } - if((vit==vitend) || (vnext == vitend)){ - 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)) { + 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& 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(*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(*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; + for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); } - _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& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling, +static int __recursiveSplit(Chain *_curve, UnaryFunction0D& 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(); - //real _min = func(it0d);++it; - real _min = FLT_MAX;++it; - real mean = 0.f; - //soc unused - real variance = 0.f; - 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 == 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._CurvilinearLengthpush_vertex_back(&(*vit)); - } - if((vit==vitend) || (vnext == vitend)){ - 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; + 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; +#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)) { + 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& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling) +int Operators::recursiveSplit(UnaryFunction0D& 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(*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(*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; + for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) { + if ((*cit)->getLength2D() < M_EPSILON) { + delete (*cit); + continue; + } + _current_chains_set.push_back(*cit); } - _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 PredicateWrapper(BinaryPredicate1D& pred) { - _pred = &pred; - } - - inline bool operator()(Interface1D* i1, Interface1D* i2) { - if ((*_pred)(*i1, *i2) < 0) - throw std::runtime_error("comparison failed"); - return _pred->result; - } + inline bool operator()(Interface1D *i1, Interface1D *i2) + { + if ((*_pred)(*i1, *i2) < 0) + throw std::runtime_error("comparison failed"); + return _pred->result; + } private: - - BinaryPredicate1D* _pred; + 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; +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; } -static Stroke* createStroke(Interface1D& inter) { - Stroke* stroke = new Stroke; - stroke->setId(inter.getId()); - - float currentCurvilignAbscissa = 0.f; - - 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(&(*it)); - if (!cp) { - sv = dynamic_cast(&(*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 < 1e-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(&(*it)); - if (!cp) { - sv = dynamic_cast(&(*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 < 1e-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. - Interface0DIterator v = stroke->verticesBegin(); - Interface0DIterator vnext = v; ++vnext; - Vec2r next((*v).getPoint2D()); - while (!vnext.isEnd()) { - current = next; - next = (*vnext).getPoint2D(); - if ((next - current).norm() < 1e-6) { - Interface0DIterator vprevious = v; - if (!vprevious.isBegin()) - --vprevious; - - // collect a set of overlapping vertices (except the first one) - std::vector overlapping_vertices; - do { - overlapping_vertices.push_back(&(*vnext)); - current = next; - ++v; ++vnext; - if (vnext.isEnd()) - break; - next = (*vnext).getPoint2D(); - } while ((next - current).norm() < 1e-6); - - Vec2r target; - bool reverse; - if (!vnext.isEnd()) { - target = (*vnext).getPoint2D(); - reverse = false; - } else if (!vprevious.isBegin()) { - target = (*vprevious).getPoint2D(); - reverse = true; - } else { - // Discard the stroke because all stroke vertices are overlapping - delete stroke; - return NULL; - } - Vec2r dir(target - current); - real dist = dir.norm(); - real len = 1e-3; // default offset length - int nvert = overlapping_vertices.size(); - if (dist < len * nvert) { - len = dist / (nvert + 1); - } - dir.normalize(); - Vec2r offset(dir * len); - //cout << "#vert " << nvert << " len " << len << " reverse? " << reverse << endl; - - // add the offset to the overlapping vertices - StrokeVertex* sv; - std::vector::iterator it = overlapping_vertices.begin(), - itend = overlapping_vertices.end(); - if (!reverse) { - int n = 1; - for (; it != itend; ++it) { - sv = dynamic_cast(*it); - sv->setPoint(sv->getPoint() + offset * n); - ++n; - } - } else { - int n = nvert; - for (; it != itend; ++it) { - sv = dynamic_cast(*it); - sv->setPoint(sv->getPoint() + offset * n); - --n; - } - } - - 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() < 1e-6) { - warning = true; - break; - } - ++v; ++vnext; - } - if (warning) { - printf("Warning: stroke contains singular points.\n"); - } - } - return stroke; +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(&(*it)); + if (!cp) { + sv = dynamic_cast(&(*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(&(*it)); + if (!cp) { + sv = dynamic_cast(&(*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. + Interface0DIterator v = stroke->verticesBegin(); + Interface0DIterator vnext = v; + ++vnext; + Vec2r next((*v).getPoint2D()); + while (!vnext.isEnd()) { + current = next; + next = (*vnext).getPoint2D(); + if ((next - current).norm() < 1.0e-6) { + Interface0DIterator vprevious = v; + if (!vprevious.isBegin()) + --vprevious; + + // collect a set of overlapping vertices (except the first one) + std::vector overlapping_vertices; + do { + overlapping_vertices.push_back(&(*vnext)); + current = next; + ++v; + ++vnext; + if (vnext.isEnd()) + break; + next = (*vnext).getPoint2D(); + } while ((next - current).norm() < 1.0e-6); + + Vec2r target; + bool reverse; + if (!vnext.isEnd()) { + target = (*vnext).getPoint2D(); + reverse = false; + } + else if (!vprevious.isBegin()) { + target = (*vprevious).getPoint2D(); + reverse = true; + } + else { + // Discard the stroke because all stroke vertices are overlapping + delete stroke; + return NULL; + } + 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 + 1); + } + dir.normalize(); + Vec2r offset(dir * len); + //cout << "#vert " << nvert << " len " << len << " reverse? " << reverse << endl; + + // add the offset to the overlapping vertices + StrokeVertex *sv; + std::vector::iterator it = overlapping_vertices.begin(), + itend = overlapping_vertices.end(); + if (!reverse) { + int n = 1; + for (; it != itend; ++it) { + sv = dynamic_cast(*it); + sv->setPoint(sv->getPoint() + offset * n); + ++n; + } + } + else { + int n = nvert; + for (; it != itend; ++it) { + sv = dynamic_cast(*it); + sv->setPoint(sv->getPoint() + offset * n); + --n; + } + } + + 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) { + printf("Warning: stroke contains singular points.\n"); + } + } + return stroke; } -inline int applyShading(Stroke& stroke, vector& shaders) { - for (vector::iterator it = shaders.begin(); it != shaders.end(); ++it) { - if ((*it)->shade(stroke) < 0) { - return -1; +inline int applyShading(Stroke& stroke, vector& shaders) +{ + for (vector::iterator it = shaders.begin(); it != shaders.end(); ++it) { + if ((*it)->shade(stroke) < 0) { + return -1; + } } - } - return 0; + return 0; } -int Operators::create(UnaryPredicate1D& pred, vector 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; +int Operators::create(UnaryPredicate1D& pred, vector 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; 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() { - 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(); +void Operators::reset() +{ + 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(); #if 0 - _current_view_edges_set.insert(_current_view_edges_set.begin(), - vm->ViewEdges().begin(), - vm->ViewEdges().end()); + _current_view_edges_set.insert(_current_view_edges_set.begin(), + vm->ViewEdges().begin(), + vm->ViewEdges().end()); #else - 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); - } + 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); + } #endif - _current_set = &_current_view_edges_set; - _current_strokes_set.clear(); + _current_set = &_current_view_edges_set; + _current_strokes_set.clear(); } diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h index d705d5af5b2..aafbc2350d9 100644 --- a/source/blender/freestyle/intern/stroke/Operators.h +++ b/source/blender/freestyle/intern/stroke/Operators.h @@ -1,311 +1,274 @@ -// -// Filename : Operators.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Class gathering stroke creation algorithms -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef OPERATORS_H -# define OPERATORS_H - -# include "../view_map/Interface1D.h" -# include -# include -# include "Predicates1D.h" -# include "Predicates0D.h" -# include "../view_map/ViewMap.h" -# include "Chain.h" -# include "ChainingIterators.h" -# include "../system/TimeStamp.h" -# include "StrokeShader.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_OPERATORS_H__ +#define __FREESTYLE_OPERATORS_H__ + +/** \file blender/freestyle/intern/stroke/Operators.h + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include +#include + +#include "Chain.h" +#include "ChainingIterators.h" +#include "Predicates0D.h" +#include "Predicates1D.h" +#include "StrokeShader.h" + +#include "../system/TimeStamp.h" + +#include "../view_map/Interface1D.h" +#include "../view_map/ViewMap.h" /*! Class defining the operators used in a style module. - * There are 4 classes of operators: Selection, Chaining, - * Splitting and Creating. All these operators are user controlled - * in the scripting language through Functors, Predicates and Shaders - * that are taken as arguments. + * There are 4 classes of operators: Selection, Chaining, Splitting and Creating. All these operators are + * user controlled in the scripting language through Functors, Predicates and Shaders that are taken as arguments. */ class LIB_STROKE_EXPORT Operators { public: + typedef vector I1DContainer; + typedef vector StrokesContainer; - typedef vector I1DContainer; - typedef vector 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.f); - - /*! 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.f); - - /*! 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& 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& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling = 0); - - /*! 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 shaders); - - // - // Data access - // - //////////////////////////////////////////////// - - static ViewEdge* getViewEdgeFromIndex(unsigned i) { - return dynamic_cast(_current_view_edges_set[i]); - } - - static Chain* getChainFromIndex(unsigned i) { - return dynamic_cast(_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(); + // + // Operators + // + //////////////////////////////////////////////// -private: + /*! 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); - Operators() {} + /*! 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& 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& 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 shaders); + + // + // Data access + // + //////////////////////////////////////////////// + + static ViewEdge *getViewEdgeFromIndex(unsigned i) + { + return dynamic_cast(_current_view_edges_set[i]); + } + + static Chain *getChainFromIndex(unsigned i) + { + return dynamic_cast(_current_chains_set[i]); + } + + static Stroke *getStrokeFromIndex(unsigned i) + { + return _current_strokes_set[i]; + } + + static unsigned getViewEdgesSize() + { + return _current_view_edges_set.size(); + } + + static unsigned getChainsSize() + { + return _current_chains_set.size(); + } + + static unsigned getStrokesSize() + { + return _current_strokes_set.size(); + } + + // + // Not exported in Python + // + ////////////////////////////////////////////////// + + static StrokesContainer *getStrokesSet() + { + return &_current_strokes_set; + } + + static void reset(); + +private: + Operators() {} - static I1DContainer _current_view_edges_set; - static I1DContainer _current_chains_set; - static I1DContainer* _current_set; - static StrokesContainer _current_strokes_set; + static I1DContainer _current_view_edges_set; + static I1DContainer _current_chains_set; + static I1DContainer *_current_set; + static StrokesContainer _current_strokes_set; }; -#endif // 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 dc9c94e0e11..0b527f9f2af 100644 --- a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp @@ -1,89 +1,106 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/PSStrokeRenderer.cpp + * \ingroup freestyle + * \brief Class to define the Postscript rendering of a stroke + * \author Stephane Grabli + * \date 10/26/2004 + */ -# include "PSStrokeRenderer.h" -# include "Canvas.h" +#include "Canvas.h" +#include "PSStrokeRenderer.h" -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; +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; } -PSStrokeRenderer::~PSStrokeRenderer(){ - Close(); +PSStrokeRenderer::~PSStrokeRenderer() +{ + Close(); } -void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{ - RenderStrokeRepBasic(iStrokeRep); +void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const +{ + RenderStrokeRepBasic(iStrokeRep); } -void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{ - vector& strips = iStrokeRep->getStrips(); - Strip::vertex_container::iterator v[3]; - StrokeVertexRep *svRep[3]; - Vec3r color[3]; - for(vector::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]); +void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const +{ + vector& strips = iStrokeRep->getStrips(); + Strip::vertex_container::iterator v[3]; + StrokeVertexRep *svRep[3]; + Vec3r color[3]; + for (vector::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]); - - 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" <point2d()[0] << " " <point2d()[1] << " moveto" << endl; - _ofstream << svRep[1]->point2d()[0] << " " <point2d()[1] << " lineto" << endl; - _ofstream << svRep[2]->point2d()[0] << " " <point2d()[1] << " lineto" << endl; - _ofstream << "closepath" << endl; - _ofstream << "fill" << endl; + while (v[2] != vertices.end()) { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); - ++v[0]; - ++v[1]; - ++v[2]; - } - } -} + 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" <point2d()[0] << " " <point2d()[1] << " moveto" << endl; + _ofstream << svRep[1]->point2d()[0] << " " <point2d()[1] << " lineto" << endl; + _ofstream << svRep[2]->point2d()[0] << " " <point2d()[1] << " lineto" << endl; + _ofstream << "closepath" << endl; + _ofstream << "fill" << endl; -void PSStrokeRenderer::Close(){ - if(_ofstream.is_open()) - _ofstream.close(); + ++v[0]; + ++v[1]; + ++v[2]; + } + } } +void PSStrokeRenderer::Close() +{ + if (_ofstream.is_open()) + _ofstream.close(); +} diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h index b30949845ab..e01ec531471 100644 --- a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h @@ -1,38 +1,45 @@ -// -// Filename : PSStrokeRenderer.h -// Author(s) : Stephane Grabli -// Purpose : Class to define the Postscript rendering of a stroke -// Date of creation : 10/26/2004 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef PSSTROKERENDERER_H -# define PSSTROKERENDERER_H - -# include "StrokeRenderer.h" -# include "../system/FreestyleConfig.h" -# include +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_PS_STROKE_RENDERER_H__ +#define __FREESTYLE_PS_STROKE_RENDERER_H__ + +/** \file blender/freestyle/intern/stroke/PSStrokeRenderer.h + * \ingroup freestyle + * \brief Class to define the Postscript rendering of a stroke + * \author Stephane Grabli + * \date 10/26/2004 + */ + +#include + +#include "StrokeRenderer.h" + +#include "../system/FreestyleConfig.h" /**********************************/ /* */ @@ -45,19 +52,18 @@ class LIB_STROKE_EXPORT PSStrokeRenderer : public StrokeRenderer { public: - PSStrokeRenderer(const char * iFileName = 0); - virtual ~PSStrokeRenderer(); + PSStrokeRenderer(const char * iFileName = 0); + 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; + mutable ofstream _ofstream; }; -#endif // PSSTROKERENDERER_H - +#endif // __FREESTYLE_PS_STROKE_RENDERER_H__ diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h index 2f5d9551b3a..796bbdef0f6 100644 --- a/source/blender/freestyle/intern/stroke/Predicates0D.h +++ b/source/blender/freestyle/intern/stroke/Predicates0D.h @@ -1,82 +1,86 @@ -// -// Filename : Predicates0D.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Class gathering stroke creation algorithms -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_PREDICATES_0D_H__ +#define __FREESTYLE_PREDICATES_0D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef PREDICATES0D_H -# define PREDICATES0D_H +/** \file blender/freestyle/intern/stroke/Predicates0D.h + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -# include "../view_map/Functions0D.h" +#include "../python/Director.h" -# include "../python/Director.h" +#include "../view_map/Functions0D.h" // // UnaryPredicate0D (base class for predicates in 0D) // /////////////////////////////////////////////////////////// -/*! Base class for Unary Predicates that work - * on Interface0DIterator. - * A UnaryPredicate0D is a functor that evaluates - * a condition on a Interface0DIterator and returns - * true or false depending on whether this condition is - * satisfied or not. + +/*! Base class for Unary Predicates that work on Interface0DIterator. + * A UnaryPredicate0D is a functor that evaluates a condition on a Interface0DIterator and returns + * true or false depending on whether this condition is satisfied or not. * The UnaryPredicate0D is used by calling its () operator. * Any inherited class must overload the () operator. */ class UnaryPredicate0D { public: - bool result; PyObject *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) { - return Director_BPy_UnaryPredicate0D___call__(this, it); - } + /*! 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) + { + return Director_BPy_UnaryPredicate0D___call__(this, it); + } }; @@ -84,43 +88,45 @@ public: // BinaryPredicate0D (base class for predicates in 0D) // /////////////////////////////////////////////////////////// + /*! Base class for Binary Predicates working on Interface0D. - * A BinaryPredicate0D is typically an ordering relation - * between two Interface0D. - * It evaluates a relation between 2 Interface0D and - * returns true or false. + * A BinaryPredicate0D is typically an ordering relation between two Interface0D. + * It evaluates a relation between 2 Interface0D and returns true or false. * It is used by calling the () operator. */ class BinaryPredicate0D { public: - - bool result; - PyObject *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) { - return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2); - } - + bool result; + PyObject *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) + { + return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2); + } }; @@ -131,42 +137,50 @@ public: 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; - } - }; - - // 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; - } - }; +// 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; + } +}; + +// 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; + } +}; } // end of namespace Predicates0D -#endif // PREDICATES0D_H +#endif // __FREESTYLE_PREDICATES_0D_H__ diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h index b1159a8332e..18e4328c4d5 100644 --- a/source/blender/freestyle/intern/stroke/Predicates1D.h +++ b/source/blender/freestyle/intern/stroke/Predicates1D.h @@ -1,85 +1,93 @@ -// -// Filename : Predicates1D.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Class gathering stroke creation algorithms -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_PREDICATES_1D_H__ +#define __FREESTYLE_PREDICATES_1D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/Predicates1D.h + * \ingroup freestyle + * \brief Class gathering stroke creation algorithms + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -#ifndef PREDICATES1D_H -# define PREDICATES1D_H +#include -# include -# include "../system/TimeStamp.h" -# include "../view_map/Interface1D.h" -# include "../view_map/Functions1D.h" -# include "AdvancedFunctions1D.h" +#include "AdvancedFunctions1D.h" -# include "../python/Director.h" +#include "../python/Director.h" + +#include "../system/TimeStamp.h" + +#include "../view_map/Interface1D.h" +#include "../view_map/Functions1D.h" // // UnaryPredicate1D (base class for predicates in 1D) // /////////////////////////////////////////////////////////// -/*! Base class for Unary Predicates that work - * on Interface1D. - * A UnaryPredicate1D is a functor that evaluates - * a condition on a Interface1D and returns - * true or false depending on whether this condition is - * satisfied or not. + +/*! Base class for Unary Predicates that work on Interface1D. + * A UnaryPredicate1D is a functor that evaluates a condition on a Interface1D and returns + * true or false depending on whether this condition is satisfied or not. * The UnaryPredicate1D is used by calling its () operator. * Any inherited class must overload the () operator. */ class UnaryPredicate1D { public: - bool result; PyObject *py_up1D; - - /*! Default constructor. */ - UnaryPredicate1D() { py_up1D = 0; } - /*! 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) { - return Director_BPy_UnaryPredicate1D___call__(this, inter); - } + /*! 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) + { + return Director_BPy_UnaryPredicate1D___call__(this, inter); + } }; @@ -87,42 +95,45 @@ public: // BinaryPredicate1D (base class for predicates in 1D) // /////////////////////////////////////////////////////////// + /*! Base class for Binary Predicates working on Interface1D. - * A BinaryPredicate1D is typically an ordering relation - * between two Interface1D. - * It evaluates a relation between 2 Interface1D and - * returns true or false. + * A BinaryPredicate1D is typically an ordering relation between two Interface1D. + * It evaluates a relation between 2 Interface1D and returns true or false. * It is used by calling the () operator. */ class BinaryPredicate1D { public: - - bool result; - PyObject *py_bp1D; - - /*! Default constructor. */ - BinaryPredicate1D() { py_bp1D = 0; } - /*! 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) { - return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2); - } + bool result; + PyObject *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) + { + return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2); + } }; @@ -133,408 +144,446 @@ public: 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; - } - }; - - // 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; - } - }; - - // 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; - }; - - // 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; - } - }; - - // 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 occluded; - Functions1D::getOccludeeF1D(inter, occluded); - for(set::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; - } - }; - - // 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(&inter); - if (!edge) { +// 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; + } +}; + +// 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; - } - 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 shapes; - Functions1D::getShapeF1D(inter, shapes); - for(set::iterator s=shapes.begin(), send=shapes.end(); - s!=send; - ++s){ - if((*s)->getId() == _id) { - result = true; - 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; +}; + +// 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; - } - }; - - // 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; + 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 occluded; + Functions1D::getOccludeeF1D(inter, occluded); + for (set::iterator os = occluded.begin(), osend = occluded.end(); os != osend; ++os) { + if ((*os) == 0) { + 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; + 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; + } +}; + +// 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(&inter); + if (!edge) + { + result = false; return 0; - } - prev = p; } - } - result = false; - return 0; - } - }; - - // - // Binary Predicates definitions - // - /////////////////////////////////////////////////////////// - - // 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; - } - }; - - // 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; - } - }; - - // 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; - } - }; - - // 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 shapes1; - Functions1D::getShapeF1D(i1, shapes1); - set shapes2; - Functions1D::getShapeF1D(i2, shapes2); - // FIXME:// n2 algo, can do better... - for(set::iterator s=shapes1.begin(), send=shapes1.end(); - s!=send; - ++s){ - Id current = (*s)->getId(); - for(set::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; - } - }; + 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 shapes; + Functions1D::getShapeF1D(inter, shapes); + for (set::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; + } +}; + +// +// Binary Predicates definitions +// +/////////////////////////////////////////////////////////// + +// 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; + } +}; + +// 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; + } +}; + +// 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; + } +}; + +// 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 shapes1; + Functions1D::getShapeF1D(i1, shapes1); + set shapes2; + Functions1D::getShapeF1D(i2, shapes2); + // FIXME:// n2 algo, can do better... + for (set::iterator s = shapes1.begin(), send = shapes1.end(); s != send; ++s) { + Id current = (*s)->getId(); + for (set::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; + } +}; + } // end of namespace Predicates1D -#endif // PREDICATES1D_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 ef068f15061..38a126d0f66 100644 --- a/source/blender/freestyle/intern/stroke/QInformationMap.h +++ b/source/blender/freestyle/intern/stroke/QInformationMap.h @@ -1,58 +1,73 @@ -// -// Filename : QInformationMap.h -// Author : Stephane Grabli -// Purpose : Class defining an information map using a QImage -// Date of creation : 04/01/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef QINFORMATIONMAP_H -# define QINFORMATIONMAP_H - -# include -# include "InformationMap.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_Q_INFORMATION_MAP_H__ +#define __FREESTYLE_Q_INFORMATION_MAP_H__ + +/** \file blender/freestyle/intern/stroke/QInformationMap.h + * \ingroup freestyle + * \brief Class defining an information map using a QImage + * \author Stephane Grabli + * \date 04/01/2003 + */ + +#include + +#include "InformationMap.h" class QInformationMap : public InformationMap { private: - QImage _map; // the image or a piece of image + QImage _map; // the image or a piece of image public: - QInformationMap(); - QInformationMap(const QImage&); - QInformationMap(const QInformationMap&); - QInformationMap& operator=(const QInformationMap&); + 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); - //float getSmoothedPixel(int x, int y, float sigma = 0.2f) - 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 const QImage& map() const {return _map;} - inline void setMap(const QImage& iMap, float iw, float ih) {_map = iMap.copy();_w=iw;_h=ih;} + 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); + virtual float computeGaussian(int x, int y); }; -#endif // QINFORMATIONMAP_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 b42e673b4be..477092f2e7a 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.cpp +++ b/source/blender/freestyle/intern/stroke/Stroke.cpp @@ -1,947 +1,940 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/Stroke.cpp + * \ingroup freestyle + * \brief Classes to define a stroke + * \author Stephane Grabli + * \date 09/09/2002 + */ #include "Stroke.h" -#include "StrokeRenderer.h" -#include "StrokeIterators.h" #include "StrokeAdvancedIterators.h" +#include "StrokeIterators.h" +#include "StrokeRenderer.h" - /**********************************/ - /* */ - /* */ - /* StrokeAttribute */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* StrokeAttribute */ +/* */ +/* */ +/**********************************/ StrokeAttribute::StrokeAttribute() { - int i; - _alpha = 1.f; - _thickness[0] = 1.f; - _thickness[1] = 1.f; - for(i=0; i<3; ++i) - _color[i] = 0.2f; - _color[0]=0.8; - _userAttributesReal = 0; - _userAttributesVec2f = 0; - _userAttributesVec3f = 0; - _visible = true; + 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 = 0; - if(iBrother._userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f); - else - _userAttributesVec2f = 0; - if(iBrother._userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f); - else - _userAttributesVec3f = 0; -} -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 = 0; - _userAttributesVec2f = 0; - _userAttributesVec3f = 0; + _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) +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 = true; - - // FIXME: a verifier (et a ameliorer) - 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(), it2end=a2._userAttributesReal->end(); - for(; (it1!=it1end); ++it1){ - (*_userAttributesReal)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); - } - } - }else{ - _userAttributesReal = 0; - } - 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(), it2end=a2._userAttributesVec2f->end(); - for(; (it1!=it1end); ++it1){ - (*_userAttributesVec2f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); - } - } - }else{ - _userAttributesVec2f = 0; - } - 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(), it2end=a2._userAttributesVec3f->end(); - for(; (it1!=it1end); ++it1){ - (*_userAttributesVec3f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second); - } - } - }else{ - _userAttributesVec3f = 0; - } + _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 = true; + + // 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(), it2end = a2._userAttributesReal->end(); + for (; it1 != it1end; ++it1) { + (*_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(), it2end = a2._userAttributesVec2f->end(); + for (; it1 != it1end; ++it1) { + (*_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(), it2end = a2._userAttributesVec3f->end(); + for (; it1 != it1end; ++it1) { + (*_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; - } + 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 = 0; - } - if(iBrother._userAttributesVec2f){ - if(!_userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap; - _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f)); - }else{ - _userAttributesVec2f = 0; - } - if(iBrother._userAttributesVec3f){ - if(!_userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap; - _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f)); - }else{ - _userAttributesVec3f = 0; - } - return *this; -} - -float StrokeAttribute::getAttributeReal(const char *iName) const{ - if(!_userAttributesReal){ - cout << "StrokeAttribute warning: no real attribute was defined"<< endl; - return 0; - } - realMap::iterator a = _userAttributesReal->find(iName); - if(a ==_userAttributesReal->end()){ - cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl; - return 0; - } - return (*a).second; -} -Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const{ - if(!_userAttributesVec2f){ - cout << "StrokeAttribute warning: no Vec2f attribute was defined "<< endl; - return 0; - } - Vec2fMap::iterator a = _userAttributesVec2f->find(iName); - if(a ==_userAttributesVec2f->end()){ - 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){ - cout << "StrokeAttribute warning: no Vec3f attribute was defined"<< endl; - return 0; - } - Vec3fMap::iterator a = _userAttributesVec3f->find(iName); - if(a ==_userAttributesVec3f->end()){ - 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; -} -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; -} -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; -} -void StrokeAttribute::setAttributeReal(const char *iName, float att){ - if(!_userAttributesReal) - _userAttributesReal = new realMap; - (*_userAttributesReal)[iName] = att; -} -void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att){ - if(!_userAttributesVec2f) - _userAttributesVec2f = new Vec2fMap; - (*_userAttributesVec2f)[iName] = att; +{ + 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) { + cout << "StrokeAttribute warning: no real attribute was defined" << endl; + return 0.0f; + } + realMap::iterator a = _userAttributesReal->find(iName); + if (a == _userAttributesReal->end()) { + 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) { + cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl; + return 0; + } + Vec2fMap::iterator a = _userAttributesVec2f->find(iName); + if (a == _userAttributesVec2f->end()) { + 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) { + cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl; + return 0; + } + Vec3fMap::iterator a = _userAttributesVec3f->find(iName); + if (a == _userAttributesVec3f->end()) { + 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; } -void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att){ - if(!_userAttributesVec3f) - _userAttributesVec3f = new Vec3fMap; - (*_userAttributesVec3f)[iName] = att; + +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; } - /**********************************/ - /* */ - /* */ - /* StrokeVertex */ - /* */ - /* */ - /**********************************/ -StrokeVertex::StrokeVertex() +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; +} -:CurvePoint() +void StrokeAttribute::setAttributeReal(const char *iName, float att) { + if (!_userAttributesReal) + _userAttributesReal = new realMap; + (*_userAttributesReal)[iName] = att; +} - _CurvilignAbscissa = 0.f; +void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att) +{ + if (!_userAttributesVec2f) + _userAttributesVec2f = new Vec2fMap; + (*_userAttributesVec2f)[iName] = att; +} - _StrokeLength = 0.f; +void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att) +{ + if (!_userAttributesVec3f) + _userAttributesVec3f = new Vec3fMap; + (*_userAttributesVec3f)[iName] = att; } +/**********************************/ +/* */ +/* */ +/* StrokeVertex */ +/* */ +/* */ +/**********************************/ -StrokeVertex::StrokeVertex(const StrokeVertex& iBrother) +StrokeVertex::StrokeVertex() : CurvePoint() +{ + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; +} -:CurvePoint(iBrother) +StrokeVertex::StrokeVertex(const StrokeVertex& iBrother) : CurvePoint(iBrother) { - _Attribute = iBrother._Attribute; + _Attribute = iBrother._Attribute; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; +} - _CurvilignAbscissa = 0.f; +StrokeVertex::StrokeVertex(SVertex *iSVertex) : CurvePoint(iSVertex, 0, 0.0f) +{ + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; +} - _StrokeLength = 0.f; +StrokeVertex::StrokeVertex(CurvePoint *iPoint) : CurvePoint(*iPoint) +{ + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; } -StrokeVertex::StrokeVertex(SVertex *iSVertex) -:CurvePoint(iSVertex,0,0.f) +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(); +} +StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute) : CurvePoint(iSVertex, 0, 0.0f) { + _Attribute = iAttribute; + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; +} - _CurvilignAbscissa = 0.f; +StrokeVertex::~StrokeVertex() {} - _StrokeLength = 0.f; +StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother) +{ + ((CurvePoint*)this)->operator=(iBrother); + _Attribute = iBrother._Attribute; -} + _CurvilignAbscissa = 0.0f; + _StrokeLength = 0.0f; + return *this; +} -StrokeVertex::StrokeVertex(CurvePoint *iPoint) -:CurvePoint(*iPoint) +/**********************************/ +/* */ +/* */ +/* Stroke */ +/* */ +/* */ +/**********************************/ +Stroke::Stroke() { + _Length = 0; + _id = 0; + _sampling = FLT_MAX; + //_mediumType = DEFAULT_STROKE; + _mediumType = OPAQUE_MEDIUM; + _textureId = 0; + _tips = false; + _rep = NULL; +} - _CurvilignAbscissa = 0.f; +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; + _tips = iBrother._tips; + if (iBrother._rep) + _rep = new StrokeRep(*(iBrother._rep)); + else + _rep = NULL; +} - _StrokeLength = 0.f; +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)); + 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); + } +} -StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3) +float Stroke::ComputeSampling(int iNVertices) +{ + if (iNVertices <= (int)_Vertices.size()) //soc + return _sampling; -:CurvePoint(iA,iB,t3) + 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; + } +}; - // interpolate attributes: +void Stroke::Resample(int iNPoints) +{ + int vertsize = strokeVerticesSize(); + if (iNPoints <= vertsize) + return; + + StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); + StrokeInternal::StrokeVertexIterator next = it; + ++next; + StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); + + vertex_container newVertices; + real t = 0.0f; + StrokeVertex *newVertex = NULL; + vector 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((iNPoints - strokeVerticesSize()) * 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 + int NPointsToAdd = iNPoints - vertsize; + bool checkEveryone = false; + while (N < NPointsToAdd) { + for (vector::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 = true; + N++; + if (N == NPointsToAdd) + break; + } + } + checkEveryone = true; + } + //actually resample: + for (vector::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(); + + if (_rep) { + delete _rep; + _rep = new StrokeRep(this); + } +} - _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3); - _CurvilignAbscissa = (1-t3)*iA->curvilinearAbscissa()+t3*iB->curvilinearAbscissa(); - _StrokeLength = iA->strokeLength(); +void Stroke::Resample(float iSampling) +{ + //cerr << "old size :" << strokeVerticesSize() << endl; + if (iSampling == 0) + return; + if (iSampling >= _sampling) + return; + + _sampling = iSampling; + // Resample... + //real curvilinearLength = 0.0f; + vertex_container newVertices; + real t = 0.0f; + 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)); + Vec3r a((it)->point2d()); + Vec3r b((next)->point2d()); + Vec3r 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; + float limit = 0.99f; + 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(); + + if (_rep) { + delete _rep; + _rep = new StrokeRep(this); + } +} +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(); } - +void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next) +{ + vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); -StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute) + vertex_container::iterator itnext = next.getIt(); + _Vertices.insert(itnext, iVertex); + UpdateLength(); +} -:CurvePoint(iSVertex,0,0.f) +void Stroke::UpdateLength() +{ + // recompute various values (length, curvilign abscissa) + float curvabsc = 0.0f; + vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); + vertex_container::iterator previous = it; + for (; it != itend; ++it) { + curvabsc += ((*it)->point2d() - (*previous)->point2d()).norm(); + (*it)->setCurvilinearAbscissa(curvabsc); + previous = it; + } + _Length = curvabsc; + for (; 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()); +} - _Attribute = iAttribute; +Stroke::const_vertex_iterator Stroke::vertices_end() const +{ + return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); +} - _CurvilignAbscissa = 0.f; +Stroke::vertex_iterator Stroke::vertices_end() +{ + return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end()); +} - _StrokeLength = 0.f; +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()); +} +StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() +{ + return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()); } -StrokeVertex::~StrokeVertex() + +Interface0DIterator Stroke::verticesBegin() { +Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), + this->_Vertices.end())); +return ret; } -StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother) -{ - ((CurvePoint*)this)->operator=(iBrother); - _Attribute = iBrother._Attribute; +Interface0DIterator Stroke::verticesEnd() +{ + Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), + this->_Vertices.end())); + return ret; +} - _CurvilignAbscissa = 0.f; +Interface0DIterator Stroke::pointsBegin(float t) +{ + return verticesBegin(); // FIXME +} - _StrokeLength = 0.f; - return *this; +Interface0DIterator Stroke::pointsEnd(float t) +{ + return verticesEnd(); } - /**********************************/ - /* */ - /* */ - /* Stroke */ - /* */ - /* */ - /**********************************/ +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()); + } +} -Stroke::Stroke() +void Stroke::Render(const StrokeRenderer *iRenderer) { - _Length = 0; - _id = 0; - _sampling = FLT_MAX; - //_mediumType = DEFAULT_STROKE; - _mediumType = OPAQUE_MEDIUM; - _textureId = 0; - _tips = false; - _rep = 0; + if (!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRep(_rep); } -Stroke::Stroke(const Stroke& iBrother) +void Stroke::RenderBasic(const StrokeRenderer *iRenderer) { - 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; - _tips = iBrother._tips; - if(iBrother._rep) - _rep = new StrokeRep(*(iBrother._rep)); - else - _rep = 0; + if (!_rep) + _rep = new StrokeRep(this); + iRenderer->RenderStrokeRepBasic(_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(); } -Stroke::~Stroke() +#if 0 +Stroke::vertex_iterator Stroke::vertices_last() { - if(!_Vertices.empty()) - { - for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end(); - v!=vend; - v++) - { - delete (*v); - } - _Vertices.clear(); - } - - _ViewEdges.clear(); - if(_rep != 0) - { - delete _rep; - _rep = 0; - } + vertex_iterator res = vertices_begin(); + vertex_iterator next = res; + ++next; + while (!next.end()) { + ++next; + ++res; + } + return res; } -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)); - return *this; +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; } +Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling) +{ + // Resample if necessary + if (sampling < _sampling) + Resample(sampling); + return _Vertices.rbegin(); +} -void Stroke::setLength(float iLength) + +inline Vec3r shaded_color(int iCombination = 0) const; + +inline Vec<3, real> Stroke::orientation2d(const_vertex_iterator it) const { - _Length = iLength; - for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end(); - v!=vend; - ++v) - { - (*v)->setStrokeLength(iLength); - } + return iterator_edge_orientation2d_function(this, it); } -float Stroke::ComputeSampling(int iNVertices) +Vec3r Stroke::orientation2d(int iCombination) const { - if(iNVertices <= (int)_Vertices.size()) //soc - return _sampling; + return edge_orientation2d_function(*this, iCombination); +} - float sampling = _Length/(float)(iNVertices-_Vertices.size()+1); - return sampling; +inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const +{ + return iterator_edge_orientation3d_function(*this, it); } -class StrokeSegment +Vec3r Stroke::orientation3d(int iCombination) const { -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; - } -}; + return edge_orientation3d_function(*this, iCombination); +} -void Stroke::Resample(int iNPoints) +Material Stroke::material() const { - int vertsize = strokeVerticesSize(); - if(iNPoints <= vertsize) - return; - - StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator next = it;++next; - StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); - - vertex_container newVertices; - real t=0.f; - StrokeVertex * newVertex = 0; - vector 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((iNPoints-strokeVerticesSize())*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 - int NPointsToAdd = iNPoints-vertsize; - bool checkEveryone = false; - while(N < NPointsToAdd) - { - for(vector::iterator s=strokeSegments.begin(), send=strokeSegments.end(); - s!=send; - ++s) - { - if(s->_sampling == 0.f) - 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 = true; - N++; - if(N == NPointsToAdd) - break; - } - } - checkEveryone = true; - } - //actually resample: - for(vector::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_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.f)) - newVertices.push_back(&(*it)); - - int newsize = newVertices.size(); - if(newsize != iNPoints) - cerr << "Warning: incorrect points number" << endl; - - _Vertices.clear(); - _Vertices = newVertices; - newVertices.clear(); - - if(_rep) - { - delete _rep; - _rep = new StrokeRep(this); - } + 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_; +} -void Stroke::Resample(float iSampling) +inline occluder_container::const_iterator occluders_begin() const { - // cerr<<"old size :"<= _sampling) - return ; - - _sampling = iSampling; - // Resample... - //real curvilinearLength = 0.f; - vertex_container newVertices; - real t=0.f; - StrokeVertex * newVertex = 0; - StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin(); - StrokeInternal::StrokeVertexIterator next = it;++next; - StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd(); - while(((it!=itend)&&(next!=itend))) - { - newVertices.push_back(&(*it)); - Vec3r a((it)->point2d()); - Vec3r b((next)->point2d()); - Vec3r 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; - float limit = 0.99f; - while(tsetCurvilinearAbscissa(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(); - - if(_rep) - { - delete _rep; - _rep = new StrokeRep(this); - } + return _FEdgeA->occluders().begin(); } -void Stroke::RemoveVertex(StrokeVertex *iVertex) +inline occluder_container::const_iterator occluders_end() const { - 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(); + return _FEdgeA->occluders().end(); } -void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next) +int Stroke::occluders_size() const { - vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end(); + return qi(); +} - vertex_container::iterator itnext = next.getIt(); - _Vertices.insert(itnext, iVertex); - UpdateLength(); +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; } -void Stroke::UpdateLength() +#if 0 +inline const polygon3d& occludee() const { - // recompute various values (length, curvilign abscissa) - float curvabsc = 0.f; - vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end(); - vertex_container::iterator previous=it; - for(; - (it!=itend); - ++it) - { - curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm(); - (*it)->setCurvilinearAbscissa(curvabsc); - previous = it; - } - _Length = curvabsc; - for(; - (it!=itend); - ++it) - { - (*it)->setStrokeLength(_Length); - } + return *(_FEdgeA->aFace()); } +#endif -//! embedding vertex iterator -Stroke::const_vertex_iterator Stroke::vertices_begin() const { 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()); } -Stroke::vertex_iterator Stroke::vertices_end() { return vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); } +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; +} -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()); +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; } -StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() { - return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()); +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; } -Interface0DIterator Stroke::verticesBegin() { - Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), - this->_Vertices.begin(), - this->_Vertices.end())); - return ret; +real Stroke::z_discontinuity(int iCombination) const +{ + return z_discontinuity_edge_function(*this, iCombination); } -Interface0DIterator Stroke::verticesEnd() { - Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), - this->_Vertices.begin(), - this->_Vertices.end())); - return ret; +Vec3r Stroke::curvature2d_as_vector(int iCombination) const +{ + return curvature2d_as_vector_edge_function(*this, iCombination); } -Interface0DIterator Stroke::pointsBegin(float t) { - return verticesBegin(); // FIXME +real Stroke::curvature2d_as_angle(int iCombination) const +{ + return curvature2d_as_angle_edge_function(*this, iCombination); } -Interface0DIterator Stroke::pointsEnd(float t) { - return verticesEnd(); +float Stroke::shape_importance(int iCombination) const +{ + return shape_importance_edge_function(*this, iCombination); } -void Stroke::ScaleThickness(float iFactor) + +float Stroke::local_average_depth(int iCombination ) const { - 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()); - } + return local_average_depth_edge_function(*this, iCombination); } -void Stroke::Render(const StrokeRenderer *iRenderer) +float Stroke::local_depth_variance(int iCombination) const { - if(!_rep) - _rep = new StrokeRep(this); - iRenderer->RenderStrokeRep(_rep); + return local_depth_variance_edge_function(*this, iCombination); } -void Stroke::RenderBasic(const StrokeRenderer *iRenderer) +real Stroke::local_average_density(float sigma , int iCombination ) const { - if(!_rep) - _rep = new StrokeRep(this); - iRenderer->RenderStrokeRepBasic(_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(); -} -// -//Stroke::vertex_iterator Stroke::vertices_last() -//{ -// 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; -//} - -//Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling) -//{ -// // Resample if necessary -// if(sampling < _sampling) -// Resample(sampling); -// return _Vertices.rbegin(); -//} - - -//inline Vec3r shaded_color(int iCombination = 0) const ; -//inline Vec<3,real> Stroke::orientation2d(const_vertex_iterator it) const -//{ -// return iterator_edge_orientation2d_function(this, it); -//} -// Vec3r Stroke::orientation2d(int iCombination) const -// { -// return edge_orientation2d_function(*this, iCombination); -// } -//inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const -//{ -// return iterator_edge_orientation3d_function(*this, it); -//} -// Vec3r Stroke::orientation3d(int iCombination) const -// { -// return edge_orientation3d_function(*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; -//} - -//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_; -//} -//inline occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();} -//inline occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();} - -//int Stroke::occluders_size() const -//{ -// 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; -//} -////inline const polygon3d& occludee() const {return *(_FEdgeA->aFace());} -//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 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 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; -//} - -// real Stroke::z_discontinuity(int iCombination) const -// { -// return z_discontinuity_edge_function(*this, iCombination); -// } - -// Vec3r Stroke::curvature2d_as_vector(int iCombination) const -// { -// return curvature2d_as_vector_edge_function(*this, iCombination); -// } - -// real Stroke::curvature2d_as_angle(int iCombination) const -// { -// return curvature2d_as_angle_edge_function(*this, iCombination); -// } - -// float Stroke::shape_importance(int iCombination) const -// { -// return shape_importance_edge_function(*this, iCombination); -// } - - -// float Stroke::local_average_depth(int iCombination ) const -// { -// return local_average_depth_edge_function(*this, iCombination); -// } - -// float Stroke::local_depth_variance(int iCombination) const -// { -// return local_depth_variance_edge_function(*this, iCombination); -// } - -// real Stroke::local_average_density(float sigma , int iCombination ) const -// { -// return density_edge_function(*this, iCombination); -// } + return density_edge_function(*this, iCombination); +} +#endif diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h index 5b20bcac896..51733a058a9 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.h +++ b/source/blender/freestyle/intern/stroke/Stroke.h @@ -1,42 +1,50 @@ -// -// Filename : Stroke.h -// Author(s) : Stephane Grabli -// Purpose : Classes to define a stroke -// Date of creation : 09/09/2002 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_STROKE_H__ +#define __FREESTYLE_STROKE_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/Stroke.h + * \ingroup freestyle + * \brief Classes to define a stroke + * \author Stephane Grabli + * \date 09/09/2002 + */ + +#include +#include -#ifndef STROKE_H -# define STROKE_H +#include "Curve.h" -# include "../view_map/Silhouette.h" -# include -# include -# include "../system/FreestyleConfig.h" -# include "Curve.h" -# include "../view_map/Interface1D.h" -# include "../system/StringUtils.h" +#include "../view_map/Interface1D.h" +#include "../view_map/Silhouette.h" + +#include "../system/FreestyleConfig.h" +#include "../system/StringUtils.h" // @@ -45,190 +53,256 @@ //////////////////////////////////////////////////////// /*! Class to define an attribute associated to a Stroke Vertex. - * This attribute stores the color, alpha and thickness values - * for a Stroke Vertex. + * This attribute stores the color, alpha and thickness values for a Stroke Vertex. */ class LIB_STROKE_EXPORT 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); + /*! 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 realMap ; - typedef std::map Vec2fMap ; - typedef std::map Vec3fMap ; - - float _color[3]; //! the color - float _alpha; //! alpha - float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented) - bool _visible; - realMap *_userAttributesReal; - Vec2fMap *_userAttributesVec2f; - Vec3fMap *_userAttributesVec3f; + typedef std::map realMap; + typedef std::map Vec2fMap; + typedef std::map Vec3fMap; + + float _color[3]; //! the color + float _alpha; //! alpha + float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented) + bool _visible; + realMap *_userAttributesReal; + Vec2fMap *_userAttributesVec2f; + Vec3fMap *_userAttributesVec3f; }; @@ -237,87 +311,157 @@ private: // //////////////////////////////////////////////////////// -/*! Class to define a stroke vertex. - */ +/*! Class to define a stroke vertex. */ class LIB_STROKE_EXPORT StrokeVertex : public CurvePoint { public: // Implementation of Interface0D - - /*! Returns the string "StrokeVertex"*/ - virtual string getExactTypeName() const { - return "StrokeVertex"; - } + /*! 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 - 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 Vec2d */ - Vec2f getPoint () {return Vec2f((float)point2d()[0], (float)point2d()[1]);} - /*! 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 Vec2f& 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 */ - + /*! 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 Vec2d */ + Vec2f getPoint () + { + return Vec2f((float)point2d()[0], (float)point2d()[1]); + } + + /*! 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 Vec2f& 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 */ }; @@ -330,246 +474,335 @@ class StrokeRenderer; class StrokeRep; namespace StrokeInternal { - class vertex_const_traits ; - class vertex_nonconst_traits ; - template class vertex_iterator_base; - class StrokeVertexIterator; + +class vertex_const_traits; +class vertex_nonconst_traits; +template class vertex_iterator_base; +class StrokeVertexIterator; + } // 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. + * Each of these stroke vertices defines the stroke's shape and appearance at this vertex position. */ class LIB_STROKE_EXPORT 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 substraction blending).*/ + OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/ + } MediumType; - /*! 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 substraction blending).*/ - OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/ - } MediumType; - - public: - typedef std::deque vertex_container; // the vertices container - typedef std::vector viewedge_container; // the viewedges container - typedef StrokeInternal::vertex_iterator_base vertex_iterator; - typedef StrokeInternal::vertex_iterator_base const_vertex_iterator; + typedef std::deque vertex_container; // the vertices container + typedef std::vector viewedge_container; // the viewedges container + typedef StrokeInternal::vertex_iterator_base vertex_iterator; + typedef StrokeInternal::vertex_iterator_base const_vertex_iterator; public: - //typedef StrokeVertex vertex_type; + //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; - StrokeRenderer *_renderer; // mark implementation OpenGL renderer - MediumType _mediumType; - unsigned int _textureId; - bool _tips; - Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity - StrokeRep *_rep; + vertex_container _Vertices; //! The stroke's backbone vertices + Id _id; + float _Length; // The stroke length + viewedge_container _ViewEdges; + float _sampling; + StrokeRenderer *_renderer; // mark implementation OpenGL renderer + MediumType _mediumType; + unsigned int _textureId; + bool _tips; + Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity + StrokeRep *_rep; 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 - 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. - * Is vertices_size >= iNPoints, no resampling is done. - * \param iNPoints - * The number of vertices we eventually want in our stroke. - */ - void 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. - */ - void Resample(float iSampling); - - /*! 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 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 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.f); - const_vertex_iterator vertices_end() const; - vertex_iterator vertices_end(); - - /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the - * Stroke. One can specifly 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.f); - /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the - * Stroke. - */ - StrokeInternal::StrokeVertexIterator strokeVerticesEnd(); - /*! Returns the number of StrokeVertex constituing 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.f); - virtual Interface0DIterator pointsEnd(float t=0.f); + /*! 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 + 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. + */ + void 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. + */ + void Resample(float iSampling); + + /*! 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 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 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 specifly 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 constituing 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); }; - // // Implementation // @@ -579,14 +812,11 @@ public: template 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; } -#endif // 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 2768a2fd794..adaa5548bf9 100644 --- a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h +++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h @@ -1,142 +1,191 @@ -// -// Filename : StrokeAdvancedIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the elements of the Stroke -// Can't be used in python -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKEADVANCEDITERATORS_H -# define STROKEADVANCEDITERATORS_H - -# include "Stroke.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__ +#define __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__ + +/** \file blender/freestyle/intern/stroke/StrokeAdvancedIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the elements of the Stroke. Can't be used in python + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include "Stroke.h" namespace StrokeInternal { - class vertex_const_traits : public Const_traits { - public: - typedef std::deque vertex_container; - typedef vertex_container::const_iterator vertex_container_iterator ; - }; - class vertex_nonconst_traits : public Nonconst_traits { - public: - typedef std::deque vertex_container; //! the vertices container - typedef vertex_container::iterator vertex_container_iterator ; - }; - - - template - class vertex_iterator_base : public IteratorBase - { - public: - typedef vertex_iterator_base Self; - protected: - typedef IteratorBase parent_class; - typedef typename Traits::vertex_container_iterator vertex_container_iterator; - typedef vertex_iterator_base iterator; - typedef vertex_iterator_base 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); - } - inline Self operator++(int) // opérateur correspondant à i++ - { - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - ++_it; // dans un temporaire. - return tmp; - } - inline Self& operator--() // operator corresponding to ++i - { - --_it; - return *(this); - } - inline Self operator--(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - --_it; // dans un temporaire. - 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_const_traits : public Const_traits +{ +public: + typedef std::deque vertex_container; + typedef vertex_container::const_iterator vertex_container_iterator; +}; -} // end of namespace StrokeInternal +class vertex_nonconst_traits : public Nonconst_traits +{ +public: + typedef std::deque vertex_container; //! the vertices container + typedef vertex_container::iterator vertex_container_iterator; +}; + + +template +class vertex_iterator_base : public IteratorBase +{ +public: + typedef vertex_iterator_base Self; + +protected: + typedef IteratorBase parent_class; + typedef typename Traits::vertex_container_iterator vertex_container_iterator; + typedef vertex_iterator_base iterator; + typedef vertex_iterator_base 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() {} -#endif // STROKEADVANCEDITERATORS_H + 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 +#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 903a198adc2..a101ec67618 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIO.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp @@ -1,55 +1,73 @@ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/StrokeIO.cpp + * \ingroup freestyle + * \brief Functions to manage I/O for the stroke + * \author Stephane Grabli + * \date 03/02/2004 + */ -#include "StrokeIO.h" #include "StrokeAdvancedIterators.h" +#include "StrokeIO.h" -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; +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; } -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; +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; } -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; +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; } diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h index 150c8340778..789c9c92c93 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIO.h +++ b/source/blender/freestyle/intern/stroke/StrokeIO.h @@ -1,38 +1,45 @@ -// -// Filename : StrokeIO.h -// Author(s) : Stephane Grabli -// Purpose : Functions to manage I/O for the stroke -// Date of creation : 03/02/2004 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKEIO_H -# define STROKEIO_H - -# include "Stroke.h" -# include -# include "../system/FreestyleConfig.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_IO_H__ +#define __FREESTYLE_STROKE_IO_H__ + +/** \file blender/freestyle/intern/stroke/StrokeIO.h + * \ingroup freestyle + * \brief Functions to manage I/O for the stroke + * \author Stephane Grabli + * \date 03/02/2004 + */ + +#include + +#include "Stroke.h" + +#include "../system/FreestyleConfig.h" LIB_STROKE_EXPORT ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute); @@ -43,5 +50,4 @@ ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex); LIB_STROKE_EXPORT ostream& operator<<(ostream& out, const Stroke& iStroke); - -#endif // STROKEIO_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 b51189f3990..37f6a8843bd 100644 --- a/source/blender/freestyle/intern/stroke/StrokeIterators.h +++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h @@ -1,229 +1,229 @@ -// -// Filename : StrokeIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the elements of the Stroke -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_ITERATORS_H__ +#define __FREESTYLE_STROKE_ITERATORS_H__ + +/** \file blender/freestyle/intern/stroke/StrokeIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the elements of the Stroke + * \author Stephane Grabli + * \date 01/07/2003 + */ + +#include "Stroke.h" +namespace StrokeInternal { // -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. +// StrokeVertexIterator // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKEITERATORS_H -# define STROKEITERATORS_H - -# include "Stroke.h" - -namespace StrokeInternal { - - // - // StrokeVertexIterator - // - ///////////////////////////////////////////////// - - /*! Class defining an iterator designed to iterate over - * the StrokeVertex of a Stroke. - * An instance of a StrokeVertexIterator can only be obtained - * from a Stroke by calling strokeVerticesBegin() or strokeVerticesEnd(). - * It is iterating over the same vertices as an Interface0DIterator. - * The difference resides in the object access. Indeed, an Interface0DIterator - * allows only an access to an Interface0D whereas we could need - * to access the specialized StrokeVertex type. In this case, one - * should use a StrokeVertexIterator. - * The castToInterface0DIterator() method is useful to get an Interface0DIterator - * from a StrokeVertexIterator in order to call any functions of the - * type UnaryFunction0D. - * \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. - */ - 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 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(&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 defining an iterator designed to iterate over the StrokeVertex of a Stroke. + * An instance of a StrokeVertexIterator can only be obtained from a Stroke by calling strokeVerticesBegin() or + * strokeVerticesEnd(). + * It is iterating over the same vertices as an Interface0DIterator. + * The difference resides in the object access. Indeed, an Interface0DIterator allows only an access to an + * Interface0D whereas we could need to access the specialized StrokeVertex type. In this case, one + * should use a StrokeVertexIterator. + * The castToInterface0DIterator() method is useful to get an Interface0DIterator from a StrokeVertexIterator in + * order to call any functions of the type UnaryFunction0D. + * \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. + */ +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 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(&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 - -#endif // STROKEITERATORS_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 93d695be406..b12477c3e34 100644 --- a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp @@ -1,64 +1,70 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/StrokeLayer.cpp + * \ingroup freestyle + * \brief Class to define a layer of strokes. + * \author Stephane Grabli + * \date 18/12/2002 + */ +#include "Canvas.h" #include "Stroke.h" #include "StrokeLayer.h" -#include "Canvas.h" 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 ) +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 ) +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(); } diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h index eb8e7891bdd..ff830db337a 100644 --- a/source/blender/freestyle/intern/stroke/StrokeLayer.h +++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h @@ -1,76 +1,106 @@ -// -// Filename : StrokeLayer.h -// Author : Stephane Grabli -// Purpose : Class to define a layer of strokes. -// Date of creation : 18/12/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKELAYER_H -# define STROKELAYER_H - -# include +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_LAYER_H__ +#define __FREESTYLE_STROKE_LAYER_H__ + +/** \file blender/freestyle/intern/stroke/StrokeLayer.h + * \ingroup freestyle + * \brief Class to define a layer of strokes. + * \author Stephane Grabli + * \date 18/12/2002 + */ + +#include class Stroke; class StrokeRenderer; -class StrokeLayer +class StrokeLayer { public: - typedef std::deque stroke_container; + typedef std::deque stroke_container; protected: - stroke_container _strokes; + 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);} - + 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); + } }; -#endif // STROKELAYER_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 19e5ba35fed..6f12dbf2083 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp @@ -1,26 +1,41 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/StrokeRenderer.cpp + * \ingroup freestyle + * \brief Classes to render a stroke with OpenGL + * \author Fredo Durand + * \date 09/09/2002 + */ #include "StrokeRenderer.h" + #include "../geometry/GeomUtils.h" + using namespace std; /**********************************/ @@ -34,18 +49,14 @@ using namespace std; LIB_STROKE_EXPORT TextureManager *StrokeRenderer::_textureManager = 0; -StrokeRenderer::StrokeRenderer () -{ -} +StrokeRenderer::StrokeRenderer() {} -StrokeRenderer::~StrokeRenderer () -{ -} +StrokeRenderer::~StrokeRenderer() {} bool StrokeRenderer::loadTextures() { - _textureManager->load(); - return true; + _textureManager->load(); + return true; } @@ -67,55 +78,61 @@ string TextureManager::_patterns_path; LIB_STROKE_EXPORT string TextureManager::_brushes_path; -TextureManager::TextureManager () +TextureManager::TextureManager() { - _hasLoadedTextures=false; - _pInstance = this; - _defaultTextureId = 0; + _hasLoadedTextures = false; + _pInstance = this; + _defaultTextureId = 0; } -TextureManager::~TextureManager () +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; - cout << "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! + cout << "brush file " << name << " not found" << endl; + return 0; + } + else { + return _brushesMap[bt]; + } } -void TextureManager::Options::setPatternsPath(const string& path) { - _patterns_path = path; +void TextureManager::Options::setPatternsPath(const string& path) +{ + _patterns_path = path; } -string TextureManager::Options::getPatternsPath() { - return _patterns_path; +string TextureManager::Options::getPatternsPath() +{ + return _patterns_path; } -void TextureManager::Options::setBrushesPath(const string& path) { - _brushes_path = path; +void TextureManager::Options::setBrushesPath(const string& path) +{ + _brushes_path = path; } -string TextureManager::Options::getBrushesPath() { - return _brushes_path; +string TextureManager::Options::getBrushesPath() +{ + return _brushes_path; } diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h index c7c6df635d5..ab451a14496 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h @@ -1,43 +1,49 @@ -// -// Filename : StrokeRenderer.h -// Author(s) : Fredo Durand -// Purpose : Classes to render a stroke with OpenGL -// Date of creation : 09/09/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKE_RENDERER_H -# define STROKE_RENDERER_H - -# include "Stroke.h" -# include -# include -# include -# include "../system/FreestyleConfig.h" -# include "StrokeRep.h" -# include +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_RENDERER_H__ +#define __FREESTYLE_STROKE_RENDERER_H__ + +/** \file blender/freestyle/intern/stroke/StrokeRenderer.h + * \ingroup freestyle + * \brief Classes to render a stroke with OpenGL + * \author Fredo Durand + * \date 09/09/2002 + */ +#include +#include +#include +#include + +#include "Stroke.h" +#include "StrokeRep.h" + +#include "../system/FreestyleConfig.h" /**********************************/ /* */ @@ -48,53 +54,64 @@ /**********************************/ -/*! Class to load textures - */ +/*! Class to load textures */ class LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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 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 brushesMap; - - static TextureManager * _pInstance; - bool _hasLoadedTextures; - brushesMap _brushesMap; - static string _patterns_path; - static string _brushes_path; - unsigned int _defaultTextureId; + 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 LIB_STROKE_EXPORT 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 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 brushesMap; + + static TextureManager *_pInstance; + bool _hasLoadedTextures; + brushesMap _brushesMap; + static string _patterns_path; + static string _brushes_path; + unsigned int _defaultTextureId; }; @@ -106,27 +123,23 @@ public: /* */ /**********************************/ -/*! Class to render a stroke. - Creates a triangle strip and stores it - strip is lazily created at the first rendering -*/ +/*! Class to render a stroke. Creates a triangle strip and stores it strip is lazily created at the first rendering */ class LIB_STROKE_EXPORT StrokeRenderer { - public: - StrokeRenderer(); - virtual ~StrokeRenderer (); - - /*! 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() ; - - //static unsigned int getTextureIndex(unsigned int index) ; - static TextureManager *_textureManager; -}; +public: + StrokeRenderer(); + virtual ~StrokeRenderer(); + /*! 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(); + + //static unsigned int getTextureIndex(unsigned int index); + static TextureManager *_textureManager; +}; -#endif // 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 91f9d866c86..e69b4dab712 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp @@ -1,652 +1,689 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/stroke/StrokeRep.cpp + * \ingroup freestyle + * \brief Class to define the representation of a stroke (for display purpose) + * \author Stephane Grabli + * \date 05/03/2003 + */ #include "Stroke.h" -#include "StrokeRep.h" -#include "StrokeRenderer.h" #include "StrokeAdvancedIterators.h" #include "StrokeIterators.h" +#include "StrokeRenderer.h" +#include "StrokeRep.h" using namespace std; // // STROKE VERTEX REP ///////////////////////////////////// -StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother){ - _point2d = iBrother._point2d; - _texCoord = iBrother._texCoord; - _color = iBrother._color; - _alpha = iBrother._alpha; + +StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother) +{ + _point2d = iBrother._point2d; + _texCoord = iBrother._texCoord; + _color = iBrother._color; + _alpha = iBrother._alpha; } // // STRIP ///////////////////////////////////// -Strip::Strip(const vector& iStrokeVertices, bool hasTips, bool beginTip, bool endTip){ - createStrip(iStrokeVertices); - if (!hasTips) - computeTexCoord (iStrokeVertices); - else - computeTexCoordWithTips (iStrokeVertices, beginTip, endTip); +Strip::Strip(const vector& iStrokeVertices, bool hasTips, bool beginTip, bool endTip) +{ + createStrip(iStrokeVertices); + if (!hasTips) + computeTexCoord (iStrokeVertices); + else + computeTexCoordWithTips (iStrokeVertices, beginTip, endTip); } -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; + +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; } -Strip::~Strip(){ - if(!_vertices.empty()){ - for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end(); - v!=vend; - ++v){ - delete (*v); - } - _vertices.clear(); - } +Strip::~Strip() +{ + if (!_vertices.empty()) { + for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) { + delete (*v); + } + _vertices.clear(); + } } ////////////////////////// // Strip creation ////////////////////////// + #define EPS_SINGULARITY_RENDERER 0.05 #define ZERO 0.00001 #define MAX_RATIO_LENGTH_SINGU 2 -#define HUGE_COORD 1e4 +#define HUGE_COORD 1.0e4 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); } -static real crossP(const Vec2r& A, const Vec2r& B){ - return A[0]*B[1] - A[1]*B[0]; +static real crossP(const Vec2r& A, const Vec2r& B) +{ + return A[0] * B[1] - A[1] * B[0]; } -void -Strip::createStrip (const vector& iStrokeVertices) +void Strip::createStrip (const vector& iStrokeVertices) { - //computeParameterization(); - if (iStrokeVertices.size() <2) - { - cerr << "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::const_iterator v ,vend, v2, vPrev; - StrokeVertex *sv, *sv2, *svPrev; - - //special case of first vertex - v=iStrokeVertices.begin(); - sv=*v; - vPrev=v; //in case the stroke has only 2 vertices; - ++v; sv2=*v; - 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"); - userDir.normalize(); - real dp = userDir*orthDir; - if(dp<0) - userDir = userDir*(-1.f); - stripDir = userDir; - } - 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)); - - // 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; - // } - // } - - int i=2; //2 because we have already processed the first vertex - - for(vend=iStrokeVertices.end(); - v!=vend; - v++){ - v2=v; ++v2; - if (v2==vend) break; - 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"); - userDir.normalize(); - real dp = userDir*orthDir; - if(dp<0) - userDir = userDir*(-1.f); - stripDir = userDir; - } - - //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"); - userDir.normalize(); - real dp = userDir*orthDir; - if(dp<0) - userDir = userDir*(-1.f); - stripDirPrev = userDir; - } - - 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 ((dirNormpoint2d()-p); - if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) || - (dirNormpoint2d()) - || (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) || - (dirNormpoint2d()) - || (fabs(stripDir * dir)setPoint2d(p-thickness[0]*stripDir); - - vPrev=v; - } // 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"); - userDir.normalize(); - real dp = userDir*orthDir; - if(dp<0) - userDir = userDir*(-1.f); - stripDirLast = userDir; - } - 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)); - int n = i; - ++i; - - // 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; - // } - // } - - _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 (i != 2*(int)iStrokeVertices.size()) - cerr << "Warning: problem with stripe size\n"; - - cleanUpSingularities (iStrokeVertices); -} + //computeParameterization(); + if (iStrokeVertices.size() < 2) { + cerr << "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::const_iterator v ,vend, v2, vPrev; + StrokeVertex *sv, *sv2, *svPrev; + + //special case of first vertex + v = iStrokeVertices.begin(); + sv = *v; + vPrev = v; //in case the stroke has only 2 vertices; + ++v; + sv2 = *v; + 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"); + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDir = userDir; + } + 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; + } + } +#endif + + int i = 2; // 2 because we have already processed the first vertex + + for (vend = iStrokeVertices.end(); v != vend; ++v) { + v2 = v; + ++v2; + if (v2 == vend) + break; + 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"); + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDir = userDir; + } + + //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"); + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDirPrev = userDir; + } + + 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); + } + + vPrev = v; + } // 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"); + userDir.normalize(); + real dp = userDir * orthDir; + if (dp < 0) + userDir = userDir * (-1.0f); + stripDirLast = userDir; + } + 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)); + int n = i; + ++i; + +#if 0 + // 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 (i != 2 * (int)iStrokeVertices.size()) + cerr << "Warning: problem with stripe size\n"; + + cleanUpSingularities (iStrokeVertices); +} // CLEAN UP ///////////////////////// -void -Strip::cleanUpSingularities (const vector& iStrokeVertices) +void Strip::cleanUpSingularities (const vector& iStrokeVertices) { - int k; - int sizeStrip = _vertices.size(); - - for (k=0; kpoint2d())) - { - cerr << "Warning: strip vertex " << k << " non valid" << endl; - return; - } - - //return; - if (iStrokeVertices.size()<2) return; - int i=0, j; - vector::const_iterator v ,vend, v2, vPrev; -StrokeVertex *sv, *sv2; //soc unused - *svPrev; - - 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++; + int k; + int sizeStrip = _vertices.size(); + + for (k = 0; k < sizeStrip; k++) { + if (notValid(_vertices[k]->point2d())) { + cerr << "Warning: strip vertex " << k << " non valid" << endl; + return; + } } - 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; jpoint2d()); - avP=Vec2r(1.0/float(timeSinceSingu1+1)*avP); - for (j=i-timeSinceSingu1; jsetPoint2d(avP); - //_vertex[2*j]=_vertex[2*i]; - singu1=false; timeSinceSingu1=0; - } + + //return; + if (iStrokeVertices.size() < 2) + return; + int i = 0, j; + vector::const_iterator v ,vend, v2, vPrev; + StrokeVertex *sv, *sv2; //soc unused - *svPrev; + + 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 + 1; j++) + avP=Vec2r(avP + _vertices[2 * j]->point2d()); + avP = Vec2r( 1.0 / float(timeSinceSingu1 + 1) * avP); + for (j = i - timeSinceSingu1; j < i + 1; 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 + 1; j++) + avP = Vec2r(avP + _vertices[2 * j + 1]->point2d()); + avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP); + for (j = i - timeSinceSingu2; j < i + 1; j++) + _vertices[2 * j + 1]->setPoint2d(avP); + //_vertex[2 * j + 1] = _vertex[2 * i + 1]; + singu2 = false; + timeSinceSingu2 = 0; + } + } + i++; } - if ((dir2 * dir) < -ZERO) - { - singu2=true; - timeSinceSingu2++; + + 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; kpoint2d())) { + cerr << "Warning: strip vertex " << k << " non valid after cleanup" << endl; + return; + } } - 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; jpoint2d()); - avP=Vec2r(1.0/float(timeSinceSingu2+1)*avP); - for (j=i-timeSinceSingu2; jsetPoint2d(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; jpoint2d()); - avP=Vec2r(1.0/float(timeSinceSingu1)*avP); - for (j=i-timeSinceSingu1; jsetPoint2d(avP); - } - if (singu2) - { - //traverse all the vertices of the singularity and average them - Vec2r avP(0.0,0.0); - for (j=i-timeSinceSingu2; jpoint2d()); - avP=Vec2r(1.0/float(timeSinceSingu2)*avP); - for (j=i-timeSinceSingu2; jsetPoint2d(avP); - } - - - for (k=0; kpoint2d())) - { - cerr << "Warning: strip vertex " << k << " non valid after cleanup"<& iStrokeVertices) +void Strip::computeTexCoord (const vector& iStrokeVertices) { - vector::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),0)); - _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); - _vertices[i]->setAlpha(sv->attribute().getAlpha()); - i++; - _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),1)); - _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])); - _vertices[i]->setAlpha(sv->attribute().getAlpha()); - i++; - // cerr<<"col=("<attribute().getColor()[0]<<", " - // <attribute().getColor()[1]<<", "<attribute().getColor()[2]<<")"<::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), 0)); + _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; + _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 1)); + _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + _vertices[i]->setAlpha(sv->attribute().getAlpha()); + i++; +#if 0 + cerr << "col=("<attribute().getColor()[0] << ", " + << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl; +#endif + } } -void -Strip::computeTexCoordWithTips (const vector& iStrokeVertices, bool tipBegin, bool tipEnd) +void Strip::computeTexCoordWithTips (const vector& iStrokeVertices, bool tipBegin, bool tipEnd) { - //soc unused - unsigned int sizeStrip = _vertices.size()+8; //for the transition between the tip and the body - vector::const_iterator v ,vend; - StrokeVertex *sv = 0; - - v=iStrokeVertices.begin(); - vend=iStrokeVertices.end(); - float l=(*v)->strokeLength()/_averageThickness; - int tiles=int(l); - float fact=(float(tiles)+0.5)/l; - //soc unused - float uTip2=float(tiles)+0.25; - float u=0; - float uPrev=0; - int i=0; - float t; - StrokeVertexRep *tvRep1, *tvRep2; - - // cerr<<"l="< 4*_averageThickness) - // cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl; + //soc unused - unsigned int sizeStrip = _vertices.size() + 8; //for the transition between the tip and the body + vector::const_iterator v, vend; + StrokeVertex *sv = NULL; + + v = iStrokeVertices.begin(); + vend = iStrokeVertices.end(); + float l = (*v)->strokeLength() / _averageThickness; + int tiles = int(l); + float fact = (float(tiles) + 0.5) / l; + //soc unused - float uTip2 = float(tiles) + 0.25; + float u = 0; + float uPrev = 0; + int i = 0; + float t; + StrokeVertexRep *tvRep1, *tvRep2; + +#if 0 + cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess=" + << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl; +#endif + + vector::iterator currentSV = _vertices.begin(); + StrokeVertexRep *svRep; + if (tipBegin) { + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = sv->curvilinearAbscissa() / _averageThickness * fact; + if (u > 0.25) + break; + + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 1)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + uPrev = u; + } + //first transition vertex + + if (fabs(u - uPrev) > ZERO) + t = (0.25 - uPrev) / (u - uPrev); + else + t = 0; +#if 0 + if (!tiles) + t = 0.5; +#endif + tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d())); + tvRep1->setTexCoord(Vec2r(0.25, 0.5)); + tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2]))); + tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + + tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t *_vertices[i]->point2d())); + tvRep2->setTexCoord(Vec2r(0.25, 1)); + tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2]))); + tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + // copy the vertices with different texture coordinates + tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d()); + tvRep1->setTexCoord(Vec2r(0.25, 0)); + tvRep1->setColor(_vertices[i - 2]->color()); + tvRep1->setAlpha(_vertices[i - 2]->alpha()); + i++; + + tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d()); + tvRep2->setTexCoord(Vec2r(0.25, 0.5)); + tvRep2->setColor(_vertices[i - 2]->color()); + tvRep2->setAlpha(_vertices[i - 2]->alpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + } + uPrev = 0; + + //body of the stroke + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = sv->curvilinearAbscissa() / _averageThickness * fact - 0.25; + if (u > tiles) + break; + + svRep->setTexCoord(Vec2r((real)u, 0)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + uPrev = u; + } + if (tipEnd) { + //second transition vertex + if ((fabs(u - uPrev) > ZERO)) + t = (float(tiles) - uPrev) / (u - uPrev); + else + t = 0; + + tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d())); + tvRep1->setTexCoord(Vec2r((real)tiles, 0)); + tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2]))); + tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + + tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d())); + tvRep2->setTexCoord(Vec2r((real)tiles, 0.5)); + tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() + + t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2]))); + tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + //copy the vertices with different texture coordinates + tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d()); + tvRep1->setTexCoord(Vec2r(0.75, 0.5)); + tvRep1->setColor(_vertices[i - 2]->color()); + tvRep1->setAlpha(_vertices[i - 2]->alpha()); + i++; + + tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d()); + tvRep2->setTexCoord(Vec2r(0.75, 1)); + tvRep2->setColor(_vertices[i - 2]->color()); + tvRep2->setAlpha(_vertices[i - 2]->alpha()); + i++; + + currentSV = _vertices.insert(currentSV, tvRep1); + ++currentSV; + currentSV = _vertices.insert(currentSV, tvRep2); + ++currentSV; + + //end tip + for (; v != vend; v++) { + sv = (*v); + svRep = *currentSV; + u = 0.75 + sv->curvilinearAbscissa() / _averageThickness * fact - float(tiles) - 0.25; + + svRep->setTexCoord(Vec2r((real)u, 0.5)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + + svRep = *currentSV; + svRep->setTexCoord(Vec2r((real)u, 1)); + svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1], + sv->attribute().getColor()[2])); + svRep->setAlpha(sv->attribute().getAlpha()); + i++; + ++currentSV; + } + } + +#if 0 + cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl; + + 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; + + 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 } // @@ -655,97 +692,98 @@ Strip::computeTexCoordWithTips (const vector& iStrokeVertices, bo StrokeRep::StrokeRep() { - _stroke = 0; - _strokeType=Stroke::OPAQUE_MEDIUM; - TextureManager * ptm = TextureManager::getInstance(); - if(ptm) - _textureId = ptm->getDefaultTextureId(); - // _averageTextureAlpha=0.5; //default value - // if (_strokeType==OIL_STROKE) - // _averageTextureAlpha=0.75; - // if (_strokeType>=NO_BLEND_STROKE) - // _averageTextureAlpha=1.0 -} + _stroke = 0; + _strokeType = Stroke::OPAQUE_MEDIUM; + 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 +#endif +} StrokeRep::StrokeRep(Stroke *iStroke) { - _stroke = iStroke; - _strokeType = iStroke->getMediumType(); - _textureId = iStroke->getTextureId(); - if(_textureId == 0){ - TextureManager * ptm = TextureManager::getInstance(); - if(ptm) - _textureId = ptm->getDefaultTextureId(); - } - - // _averageTextureAlpha=0.5; //default value - // if (_strokeType==OIL_STROKE) - // _averageTextureAlpha=0.75; - // if (_strokeType>=NO_BLEND_STROKE) - // _averageTextureAlpha=1.0; - create(); + _stroke = iStroke; + _strokeType = iStroke->getMediumType(); + _textureId = iStroke->getTextureId(); + 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; +#endif + create(); } StrokeRep::StrokeRep(const StrokeRep& iBrother) { - //soc unused - int i=0; - _stroke = iBrother._stroke; - _strokeType=iBrother._strokeType; - _textureId = iBrother._textureId; - for(vector::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; + for (vector::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::iterator s=_strips.begin(), send=_strips.end(); - s!=send; - ++s){ - delete (*s); - } - _strips.clear(); - } + if (!_strips.empty()) { + for (vector::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) { + delete (*s); + } + _strips.clear(); + } } -void StrokeRep::create(){ - vector 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, _stroke->hasTips(), first, end)); - strip.clear(); - } - first = false; - } -} +void StrokeRep::create() +{ + vector 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, _stroke->hasTips(), first, end)); + strip.clear(); + } + first = false; + } +} void StrokeRep::Render(const StrokeRenderer *iRenderer) { - iRenderer->RenderStrokeRep(this); + iRenderer->RenderStrokeRep(this); } - - - diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h index d8a8dc2d609..c8d84cb237a 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.h +++ b/source/blender/freestyle/intern/stroke/StrokeRep.h @@ -1,138 +1,217 @@ -// -// Filename : StrokeRep.h -// Author(s) : Stephane Grabli -// Purpose : Class to define the representation of a stroke -// (for display purpose) -// Date of creation : 05/03/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STROKEREP_H -# define STROKEREP_H - -# include "../geometry/Geom.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STROKE_REP_H__ +#define __FREESTYLE_STROKE_REP_H__ + +/** \file blender/freestyle/intern/stroke/StrokeRep.h + * \ingroup freestyle + * \brief Class to define the representation of a stroke (for display purpose) + * \author Stephane Grabli + * \date 05/03/2003 + */ + +#include "Stroke.h" + +#include "../geometry/Geom.h" + 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 DEFAULT_STROKE 0 -// -// # define NUMBER_STROKE_RENDERER 8 +#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 -#include "Stroke.h" +#define DEFAULT_STROKE 0 + +#define NUMBER_STROKE_RENDERER 8 + +#endif -class StrokeVertexRep{ +class StrokeVertexRep +{ public: - StrokeVertexRep(){} - StrokeVertexRep(const Vec2r& iPoint2d){_point2d=iPoint2d;} - StrokeVertexRep(const StrokeVertexRep& iBrother); - virtual ~StrokeVertexRep(){} - - inline Vec2r& point2d() {return _point2d;} - inline Vec2r& texCoord() {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){_texCoord = p;} - inline void setColor(const Vec3r& p){_color = p;} - inline void setAlpha(float a){_alpha = a;} + StrokeVertexRep(){} + + StrokeVertexRep(const Vec2r& iPoint2d) + { + _point2d = iPoint2d; + } + + StrokeVertexRep(const StrokeVertexRep& iBrother); + + virtual ~StrokeVertexRep(){} + + inline Vec2r& point2d() + { + return _point2d; + } + + inline Vec2r& texCoord() + { + 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) + { + _texCoord = p; + } + + inline void setColor(const Vec3r& p) + { + _color = p; + } + + inline void setAlpha(float a) + { + _alpha = a; + } + protected: - Vec2r _point2d; - Vec2r _texCoord; - Vec3r _color; - float _alpha; + Vec2r _point2d; + Vec2r _texCoord; + Vec3r _color; + float _alpha; }; -class Strip{ -public: - typedef std::vector vertex_container; -protected: - vertex_container _vertices; - float _averageThickness; +class Strip +{ +public: + typedef std::vector vertex_container; +protected: + vertex_container _vertices; + float _averageThickness; public: - Strip(const std::vector& iStrokeVertices, bool hasTips=false, bool tipBegin=false, bool tipEnd=false) ; - Strip(const Strip& iBrother); - virtual ~Strip() ; + Strip(const std::vector& iStrokeVertices, bool hasTips = false, + bool tipBegin = false, bool tipEnd = false); + Strip(const Strip& iBrother); + virtual ~Strip(); protected: - void createStrip(const std::vector& iStrokeVertices); - void cleanUpSingularities(const std::vector& iStrokeVertices); - void computeTexCoord (const std::vector& iStrokeVertices); - void computeTexCoordWithTips (const std::vector& iStrokeVertices, bool tipBegin, bool tipEnd); + void createStrip(const std::vector& iStrokeVertices); + void cleanUpSingularities(const std::vector& iStrokeVertices); + void computeTexCoord (const std::vector& iStrokeVertices); + void computeTexCoordWithTips (const std::vector& iStrokeVertices, bool tipBegin, bool tipEnd); + public: - inline int sizeStrip() const {return _vertices.size();} - inline vertex_container& vertices() {return _vertices;} + inline int sizeStrip() const + { + return _vertices.size(); + } + + inline vertex_container& vertices() + { + return _vertices; + } }; class StrokeRep { protected: - Stroke *_stroke; - vector _strips; - Stroke::MediumType _strokeType; - unsigned int _textureId; + Stroke *_stroke; + vector _strips; + Stroke::MediumType _strokeType; + unsigned int _textureId; - // float _averageTextureAlpha; - + // 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 vector& 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;} - - + 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 vector& 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; + } }; -#endif // STROKEREP_H +#endif // __FREESTYLE_STROKE_REP_H__ diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h index 63185438e91..c8364f7a737 100644 --- a/source/blender/freestyle/intern/stroke/StrokeShader.h +++ b/source/blender/freestyle/intern/stroke/StrokeShader.h @@ -1,39 +1,45 @@ -// -// Filename : StrokeShader.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Class defining StrokeShader -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#ifndef __FREESTYLE_STROKE_SHADERS_H__ +#define __FREESTYLE_STROKE_SHADERS_H__ -#ifndef SHADERS_H -# define SHADERS_H +/** \file blender/freestyle/intern/stroke/StrokeShader.h + * \ingroup freestyle + * \brief Class defining StrokeShader + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -# include -# include +#include +#include -# include "../python/Director.h" +#include "../python/Director.h" // // StrokeShader base class @@ -41,84 +47,61 @@ ////////////////////////////////////////////////////// class Stroke; + /*! Base class for Stroke Shaders. - * Any Stroke Shader must inherit from - * this class and overload the shade() method. - * A StrokeShader is designed to modify any - * Stroke's attribute such as Thickness, Color, + * Any Stroke Shader must inherit from this class and overload the shade() method. + * A StrokeShader is designed to modify any Stroke's attribute such as Thickness, Color, * Geometry, Texture, Blending mode... - * The basic way to achieve this operation consists - * in iterating over the StrokeVertices of the Stroke + * The basic way to achieve this operation consists in iterating over the StrokeVertices of the Stroke * and to modify each one's StrokeAttribute. * Here is a python code example of such an iteration: * \code * it = ioStroke.strokeVerticesBegin() - * while it.isEnd() == 0: + * while not it.isEnd(): * att = it.getObject().attribute() * ## perform here any attribute modification * it.increment() * \endcode * Here is a C++ code example of such an iteration: * \code - * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); - * v!=vend; - * ++v){ - * StrokeAttribute& att = v->attribute(); - * // perform any attribute modification here... + * for(StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); + * v != vend; + * ++v) + * { + * StrokeAttribute& att = v->attribute(); + * // perform any attribute modification here... * } * \endcode */ class LIB_STROKE_EXPORT StrokeShader { public: - PyObject *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. - * The shading method is designed to modify any - * Stroke's attribute such as Thickness, Color, - * Geometry, Texture, Blending mode... - * The basic way to achieve this operation consists - * in iterating over the StrokeVertices of the Stroke - * and to modify each one's StrokeAttribute. - * Here is a python code example of such an iteration: - * \code - * it = ioStroke.strokeVerticesBegin() - * while it.isEnd() == 0: - * att = it.getObject().attribute() - * ## perform here any attribute modification - * it.increment() - * \endcode - * Here is a C++ code example of such an iteration: - * \code - * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd(); - * v!=vend; - * ++v){ - * StrokeAttribute& att = v->attribute(); - * // perform any attribute modification here... - * } - * \endcode - * \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 { - return Director_BPy_StrokeShader_shade( const_cast(this), ioStroke ); - } + /*! 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 + { + return Director_BPy_StrokeShader_shade( const_cast(this), ioStroke); + } }; -# endif // 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 a8b71f9f3c3..43cf1818fb0 100644 --- a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp @@ -1,88 +1,94 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/StrokeTesselator.cpp + * \ingroup freestyle + * \brief Class to build a Node Tree designed to be displayed from a set of strokes structure. + * \author Stephane Grabli + * \date 26/03/2002 + */ +#include "StrokeAdvancedIterators.h" #include "StrokeTesselator.h" + #include "../scene_graph/OrientedLineRep.h" #include "../scene_graph/NodeGroup.h" #include "../scene_graph/NodeShape.h" -#include "StrokeAdvancedIterators.h" -LineRep* StrokeTesselator::Tesselate(Stroke *iStroke) +LineRep *StrokeTesselator::Tesselate(Stroke *iStroke) { - if(0 == iStroke) - return 0; + if (0 == iStroke) + return 0; - 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); + LineRep* line; + line = new OrientedLineRep(); - line->setStyle(LineRep::LINE_STRIP); + 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); - 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(); + line->setStyle(LineRep::LINE_STRIP); - return line; + 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; } template -NodeGroup* StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end) +NodeGroup *StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end) { - NodeGroup *group = new NodeGroup; - NodeShape *tshape = new NodeShape; - group->AddChild(tshape); - //tshape->material().setDiffuse(0.f, 0.f, 0.f, 1.f); - 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; } diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h index 671df00ef84..e04f75a6f3e 100644 --- a/source/blender/freestyle/intern/stroke/StrokeTesselator.h +++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h @@ -1,67 +1,78 @@ -// -// Filename : StrokeTesselator.h -// Author(s) : Stephane Grabli -// Purpose : Class to build a Node Tree designed to be displayed -// from a set of strokes structure. -// Date of creation : 26/03/2002 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_STROKE_TESSELATOR_H__ +#define __FREESTYLE_STROKE_TESSELATOR_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/stroke/StrokeTesselator.h + * \ingroup freestyle + * \brief Class to build a Node Tree designed to be displayed from a set of strokes structure. + * \author Stephane Grabli + * \date 26/03/2002 + */ -#ifndef STROKETESSELATOR_H -# define STROKETESSELATOR_H +#include "Stroke.h" -# include "Stroke.h" -# include "../scene_graph/LineRep.h" +#include "../scene_graph/LineRep.h" class StrokeTesselator { public: + inline StrokeTesselator() + { + _FrsMaterial.setDiffuse(0, 0, 0, 1); + _overloadFrsMaterial = false; + } - inline StrokeTesselator() {_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;} - virtual ~StrokeTesselator() {} + virtual ~StrokeTesselator() {} - /*! Builds a line rep contained from a Stroke - */ - LineRep* Tesselate(Stroke* iStroke) ; + /*! 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 - NodeGroup* Tesselate(StrokeIterator begin, StrokeIterator end) ; + /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup + * from a set of strokes. + */ + template + NodeGroup *Tesselate(StrokeIterator begin, StrokeIterator end); - - - inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;} - inline const FrsMaterial& frs_material() const {return _FrsMaterial;} + inline void setFrsMaterial(const FrsMaterial& iMaterial) + { + _FrsMaterial = iMaterial; + _overloadFrsMaterial = true; + } -private: + inline const FrsMaterial& frs_material() const + { + return _FrsMaterial; + } - FrsMaterial _FrsMaterial; - bool _overloadFrsMaterial; +private: + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; }; -#endif // STROKETESSELATOR_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 c97a8d7f999..12f645f125b 100644 --- a/source/blender/freestyle/intern/stroke/StyleModule.h +++ b/source/blender/freestyle/intern/stroke/StyleModule.h @@ -1,172 +1,184 @@ -// -// Filename : StyleModule.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Class representing a style module -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef STYLE_MODULE_H -# define STYLE_MODULE_H - -# include -# include -# include "../system/StringUtils.h" -# include "StrokeLayer.h" -# include "../system/Interpreter.h" -# include "Operators.h" -# include "StrokeShader.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STYLE_MODULE_H__ +#define __FREESTYLE_STYLE_MODULE_H__ + +/** \file blender/freestyle/intern/stroke/StyleModule.h + * \ingroup freestyle + * \brief Class representing a style module + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include +#include + +#include "Operators.h" +#include "StrokeLayer.h" +#include "StrokeShader.h" + +#include "../system/Interpreter.h" +#include "../system/StringUtils.h" using namespace std; 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; + StyleModule(const string& file_name, Interpreter *inter) : _file_name(file_name) + { + _always_refresh = false; + _causal = false; + _drawable = true; + _modified = true; + _displayed = true; + _inter = inter; } - StrokeLayer* sl = new StrokeLayer; - for (Operators::StrokesContainer::iterator it = strokes_set->begin(); - it != strokes_set->end(); - ++it) - sl->AddStroke(*it); - - Operators::reset(); - - return sl; - } + 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); - } + virtual int interpret() + { + return _inter->interpretFile(_file_name); + } public: + // accessors + const string getFileName() const + { + return _file_name; + } - // accessors - - const string getFileName() const { - return _file_name; - } - - bool getAlwaysRefresh() const { - return _always_refresh; - } - - bool getCausal() const { - return _causal; - } + bool getAlwaysRefresh() const + { + return _always_refresh; + } - bool getDrawable() const { - return _drawable; - } + bool getCausal() const + { + return _causal; + } - bool getModified() const { - return _modified; - } + bool getDrawable() const + { + return _drawable; + } - bool getDisplayed() const { - return _displayed; - } + bool getModified() const + { + return _modified; + } - // modifiers + bool getDisplayed() const + { + return _displayed; + } - void setFileName(const string& file_name) { - _file_name = file_name; - } + // modifiers + void setFileName(const string& file_name) + { + _file_name = file_name; + } - void setAlwaysRefresh(bool b = true) { - _always_refresh = b; - } + void setAlwaysRefresh(bool b = true) + { + _always_refresh = b; + } - void setCausal(bool b = true) { - _causal = b; - } + void setCausal(bool b = true) + { + _causal = b; + } - void setDrawable(bool b = true) { - _drawable = b; - } + void setDrawable(bool b = true) + { + _drawable = b; + } - void setModified(bool b = true) { - if (_always_refresh) - return; - _modified = b; - } + void setModified(bool b = true) + { + if (_always_refresh) + return; + _modified = b; + } - void setDisplayed(bool b = true) { - _displayed = b; - } + void setDisplayed(bool b = true) + { + _displayed = b; + } private: - - string _file_name; - bool _always_refresh; - bool _causal; - bool _drawable; - bool _modified; - bool _displayed; + string _file_name; + bool _always_refresh; + bool _causal; + bool _drawable; + bool _modified; + bool _displayed; protected: - - Interpreter* _inter; + Interpreter *_inter; }; -#endif // STYLE_MODULE_H +#endif // __FREESTYLE_STYLE_MODULE_H__ diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h index 8b4b6bc80d7..cc6f5c05073 100644 --- a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h +++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h @@ -42,7 +42,7 @@ /**********************************/ /* */ /* */ -/* TextStrokeRenderer */ +/* TextStrokeRenderer */ /* */ /* */ /**********************************/ -- cgit v1.2.3