585 lines
14 KiB
C++
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__
|