Fix for the WithinImageBorderUP1D predicate not working with a ViewEdge such that

none of the SVertices are within the image boundary but an FEdge intersects with
the image boundary.

The problem was reported by edna through the BA Freestyle thread, with a .blend
file for reproducing the bug.  Thanks!
This commit is contained in:
Tamito Kajiyama
2012-05-28 23:53:28 +00:00
parent b6a9a953bc
commit eabf741a8d
5 changed files with 181 additions and 22 deletions

View File

@@ -697,27 +697,6 @@ class ObjectNamesUP1D(UnaryPredicate1D):
return not found
return found
class WithinImageBorderUP1D(UnaryPredicate1D):
def __init__(self, xmin, xmax, ymin, ymax):
UnaryPredicate1D.__init__(self)
self._xmin = xmin
self._xmax = xmax
self._ymin = ymin
self._ymax = ymax
def getName(self):
return "WithinImageBorderUP1D"
def __call__(self, inter):
it = inter.verticesBegin()
while not it.isEnd():
if self.withinBorder(it.getObject()):
return True
it.increment()
return False
def withinBorder(self, vert):
x = vert.getProjectedX()
y = vert.getProjectedY()
return self._xmin <= x <= self._xmax and self._ymin <= y <= self._ymax
# Stroke caps
def iter_stroke_vertices(stroke):
@@ -1108,7 +1087,7 @@ def process(layer_name, lineset_name):
else:
xmin, xmax = 0.0, float(w)
ymin, ymax = 0.0, float(h)
upred = WithinImageBorderUP1D(xmin, xmax, ymin, ymax)
upred = WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax)
selection_criteria.append(upred)
# select feature edges
upred = join_unary_predicates(selection_criteria, AndUP1D)

View File

@@ -12,6 +12,7 @@
#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h"
#include "UnaryPredicate1D/BPy_ShapeUP1D.h"
#include "UnaryPredicate1D/BPy_TrueUP1D.h"
#include "UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h"
#ifdef __cplusplus
extern "C" {
@@ -75,6 +76,11 @@ int UnaryPredicate1D_Init( PyObject *module )
Py_INCREF( &TrueUP1D_Type );
PyModule_AddObject(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type);
if( PyType_Ready( &WithinImageBoundaryUP1D_Type ) < 0 )
return -1;
Py_INCREF( &WithinImageBoundaryUP1D_Type );
PyModule_AddObject(module, "WithinImageBoundaryUP1D", (PyObject *)&WithinImageBoundaryUP1D_Type);
return 0;
}

View File

@@ -0,0 +1,88 @@
#include "BPy_WithinImageBoundaryUP1D.h"
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////////////////
//------------------------INSTANCE METHODS ----------------------------------
static char WithinImageBoundaryUP1D___doc__[] =
"Class hierarchy: :class:`UnaryPredicate1D` > :class:`WithinImageBoundaryUP1D`\n"
"\n"
".. method:: __init__(xmin, ymin, xmax, ymax)\n"
"\n"
" Builds an WithinImageBoundaryUP1D object.\n"
"\n"
" :arg xmin: X lower bound of the image boundary.\n"
" :type xmin: float\n"
" :arg ymin: Y lower bound of the image boundary.\n"
" :type ymin: float\n"
" :arg xmax: X upper bound of the image boundary.\n"
" :type xmax: float\n"
" :arg ymax: Y upper bound of the image boundary.\n"
" :type ymax: float\n"
"\n"
".. method:: __call__(inter)\n"
"\n"
" Returns true if the Interface1D intersects with image boundary.\n";
static int WithinImageBoundaryUP1D___init__( BPy_WithinImageBoundaryUP1D* self, PyObject *args )
{
double xmin, ymin, xmax, ymax;
if(!( PyArg_ParseTuple(args, "dddd", &xmin, &ymin, &xmax, &ymax) ))
return -1;
self->py_up1D.up1D = new Predicates1D::WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax);
return 0;
}
/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
PyTypeObject WithinImageBoundaryUP1D_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"WithinImageBoundaryUP1D", /* tp_name */
sizeof(BPy_WithinImageBoundaryUP1D), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
WithinImageBoundaryUP1D___doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&UnaryPredicate1D_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)WithinImageBoundaryUP1D___init__, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,29 @@
#ifndef FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H
#define FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H
#include "../BPy_UnaryPredicate1D.h"
#ifdef __cplusplus
extern "C" {
#endif
///////////////////////////////////////////////////////////////////////////////////////////
#include <Python.h>
extern PyTypeObject WithinImageBoundaryUP1D_Type;
#define BPy_WithinImageBoundaryUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &WithinImageBoundaryUP1D_Type) )
/*---------------------------Python BPy_WithinImageBoundaryUP1D structure definition----------*/
typedef struct {
BPy_UnaryPredicate1D py_up1D;
} BPy_WithinImageBoundaryUP1D;
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif /* FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H */

View File

@@ -358,6 +358,63 @@ namespace Predicates1D {
}
};
// 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
//