This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/freestyle/intern/stroke/Predicates1D.h
2019-05-31 22:55:15 +10:00

585 lines
14 KiB
C++

/*
* 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.
*/
#ifndef __FREESTYLE_PREDICATES_1D_H__
#define __FREESTYLE_PREDICATES_1D_H__
/** \file
* \ingroup freestyle
* \brief Class gathering stroke creation algorithms
*/
#include <string>
#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<ViewShape *> occluded;
Functions1D::getOccludeeF1D(inter, occluded);
for (set<ViewShape *>::iterator os = occluded.begin(), osend = occluded.end(); os != osend;
++os) {
if ((*os) == 0) {
result = true;
return 0;
}
}
}
result = false;
return 0;
}
};
// EqualToTimeStampUP1D
/*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */
class EqualToTimeStampUP1D : public UnaryPredicate1D {
protected:
unsigned _timeStamp;
public:
EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D()
{
_timeStamp = ts;
}
/*! Returns the string "EqualToTimeStampUP1D"*/
string getName() const
{
return "EqualToTimeStampUP1D";
}
/*! The () operator. */
int operator()(Interface1D &inter)
{
result = (inter.getTimeStamp() == _timeStamp);
return 0;
}
};
// EqualToChainingTimeStampUP1D
/*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */
class EqualToChainingTimeStampUP1D : public UnaryPredicate1D {
protected:
unsigned _timeStamp;
public:
EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D()
{
_timeStamp = ts;
}
/*! Returns the string "EqualToChainingTimeStampUP1D"*/
string getName() const
{
return "EqualToChainingTimeStampUP1D";
}
/*! The () operator. */
int operator()(Interface1D &inter)
{
ViewEdge *edge = dynamic_cast<ViewEdge *>(&inter);
if (!edge) {
result = false;
return 0;
}
result = (edge->getChainingTimeStamp() >= _timeStamp);
return 0;
}
};
// ShapeUP1D
/*! Returns true if the shape to which the Interface1D belongs to has the same Id as the one
* specified by the user. */
class ShapeUP1D : public UnaryPredicate1D {
private:
Id _id;
public:
/*! Builds the Predicate.
* \param idFirst:
* The first Id component.
* \param idSecond:
* The second Id component.
*/
ShapeUP1D(unsigned idFirst, unsigned idSecond = 0) : UnaryPredicate1D()
{
_id = Id(idFirst, idSecond);
}
/*! Returns the string "ShapeUP1D"*/
string getName() const
{
return "ShapeUP1D";
}
/*! The () operator. */
int operator()(Interface1D &inter)
{
set<ViewShape *> shapes;
Functions1D::getShapeF1D(inter, shapes);
for (set<ViewShape *>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) {
if ((*s)->getId() == _id) {
result = true;
return 0;
}
}
result = false;
return 0;
}
};
// 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<ViewShape *> shapes1;
Functions1D::getShapeF1D(i1, shapes1);
set<ViewShape *> shapes2;
Functions1D::getShapeF1D(i2, shapes2);
// FIXME:// n2 algo, can do better...
for (set<ViewShape *>::iterator s = shapes1.begin(), send = shapes1.end(); s != send; ++s) {
Id current = (*s)->getId();
for (set<ViewShape *>::iterator s2 = shapes2.begin(), s2end = shapes2.end(); s2 != s2end;
++s2) {
if ((*s2)->getId() == current) {
result = true;
return 0;
}
}
}
result = false;
return 0;
}
};
// ViewMapGradientNormBP1D
/*! Returns true if the evaluation of the Gradient norm Function is higher for Interface1D i1 than
* for i2. */
class ViewMapGradientNormBP1D : public BinaryPredicate1D {
private:
Functions1D::GetViewMapGradientNormF1D _func;
public:
ViewMapGradientNormBP1D(int level, IntegrationType iType = MEAN, float sampling = 2.0)
: BinaryPredicate1D(), _func(level, iType, sampling)
{
}
/*! Returns the string "ViewMapGradientNormBP1D" */
string getName() const
{
return "ViewMapGradientNormBP1D";
}
/*! The () operator. */
int operator()(Interface1D &i1, Interface1D &i2)
{
if (_func(i1) < 0) {
return -1;
}
real n1 = _func.result;
if (_func(i2) < 0) {
return -1;
}
real n2 = _func.result;
result = (n1 > n2);
return 0;
}
};
} // end of namespace Predicates1D
} /* namespace Freestyle */
#endif // __FREESTYLE_PREDICATES_1D_H__