// // Filename : Stroke.h // Author(s) : Stephane Grabli // Purpose : Classes to define a stroke // 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_H # define STROKE_H # include # include # include "../system/FreestyleConfig.h" # include "../view_map/Silhouette.h" # include "Curve.h" # include "../view_map/Interface1D.h" # include "../system/StringUtils.h" // // StrokeAttribute // //////////////////////////////////////////////////////// /*! Class to define an attribute associated to 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); 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; }; // // StrokeVertex // //////////////////////////////////////////////////////// /*! 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"; } private: StrokeAttribute _Attribute; //! The attribute associated to the vertex float _CurvilignAbscissa; //! the curvilign abscissa float _StrokeLength; // stroke length public: /*! default constructor */ StrokeVertex(); /*! Copy constructor */ StrokeVertex(const StrokeVertex& iBrother); /*! Builds a stroke vertex from a SVertex */ StrokeVertex(SVertex *iSVertex); /*! Builds a stroke vertex from a CurvePoint */ StrokeVertex(CurvePoint *iPoint); /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/ StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3); /*! Builds a stroke from a view vertex and an attribute */ StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute); /*! destructor */ virtual ~StrokeVertex(); /* operators */ /*! operator = */ StrokeVertex& operator=(const StrokeVertex& iBrother); /* accessors */ /*! Returns the 2D point x coordinate */ inline real x() const { return _Point2d[0]; } /*! Returns the 2D point y coordinate */ inline real y() const { return _Point2d[1]; } /*! Returns the 2D point coordinates as a 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 */ }; // // Stroke // //////////////////////////////////////////////////////// class StrokeRenderer; class StrokeRep; namespace StrokeInternal { 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. */ 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; 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; public: //typedef StrokeVertex vertex_type; private: vertex_container _Vertices; //! The stroke's backbone vertices Id _id; float _Length; // The stroke length viewedge_container _ViewEdges; float _sampling; 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); /* Render method */ 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();} // 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); }; // // Implementation // //////////////////////////////////////////////////////// template Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) { for(InputVertexIterator v=iBegin, vend=iEnd; v!=vend; v++) { _Vertices.push_back(*v); } _Length = 0; _id = 0; } #endif // STROKE_H