/* * ***** 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. * * ***** END GPL LICENSE BLOCK ***** */ #ifndef __FREESTYLE_PREDICATES_1D_H__ #define __FREESTYLE_PREDICATES_1D_H__ /** \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 */ #include #include "AdvancedFunctions1D.h" #include "../system/TimeStamp.h" #include "../view_map/Interface1D.h" #include "../view_map/Functions1D.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif namespace Freestyle { // // 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. * The UnaryPredicate1D is used by calling its () operator. * Any inherited class must overload the () operator. */ class UnaryPredicate1D { public: bool result; void *py_up1D; /*! Default constructor. */ UnaryPredicate1D() { py_up1D = NULL; } /*! Destructor. */ virtual ~UnaryPredicate1D() {} /*! Returns the string of the name of the UnaryPredicate1D. */ virtual string getName() const { return "UnaryPredicate1D"; } /*! The () operator. Must be overload by inherited classes. * \param inter * The Interface1D on which we wish to evaluate the predicate. * \return true if the condition is satisfied, false otherwise. */ virtual int operator()(Interface1D& inter); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryPredicate1D") #endif }; // // 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. * It is used by calling the () operator. */ class BinaryPredicate1D { public: bool result; void *py_bp1D; /*! Default constructor. */ BinaryPredicate1D() { py_bp1D = NULL; } /*! Destructor. */ virtual ~BinaryPredicate1D() {} /*! Returns the string of the name of the binary predicate. */ virtual string getName() const { return "BinaryPredicate1D"; } /*! The () operator. Must be overload by inherited classes. * It evaluates a relation between 2 Interface1D. * \param inter1 * The first Interface1D. * \param inter2 * The second Interface1D. * \return true or false. */ virtual int operator()(Interface1D& inter1, Interface1D& inter2); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BinaryPredicate1D") #endif }; // // Predicates definitions // /////////////////////////////////////////////////////////// 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) { 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; } } 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 } /* namespace Freestyle */ #endif // __FREESTYLE_PREDICATES_1D_H__