Freestyle: Partial fix for thinning strokes due to flipping stroke directions at TVertices.
A description of the problem is found in https://developer.blender.org/T36425#19 . The cause of the issue was identified as roudning errors in Operators::createStroke() due to insufficient numerical precision. Precision promotion from float to double was done in the return values of getPoint3D/2D methods in Interface0D and its subclasses in C++ (data members stored in the 0D classes have already been in double precision).
This commit is contained in:
parent
aef443ab2d
commit
08528f577d
Notes:
blender-bot
2023-02-14 11:57:23 +01:00
Referenced by commit 4c38e826dc
, Fix for a missing code update in my commit rB08528f577dcb.
Referenced by issue #36425, freestyle edge marks not working
|
@ -95,7 +95,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 3D point. */
|
||||
virtual Vec3f getPoint3D() const
|
||||
virtual Vec3r getPoint3D() const
|
||||
{
|
||||
return _Point3d;
|
||||
}
|
||||
|
@ -119,9 +119,9 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 2D point. */
|
||||
virtual Vec2f getPoint2D() const
|
||||
virtual Vec2r getPoint2D() const
|
||||
{
|
||||
return Vec2f((float)_Point2d.x(), (float)_Point2d.y());
|
||||
return Vec2r(_Point2d.x(), _Point2d.y());
|
||||
}
|
||||
|
||||
virtual FEdge *getFEdge(Interface0D& inter);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Operators.h"
|
||||
#include "Canvas.h"
|
||||
#include "Stroke.h"
|
||||
#include "StrokeIterators.h"
|
||||
#include "CurveIterators.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
|
@ -1092,20 +1093,20 @@ static Stroke *createStroke(Interface1D& inter)
|
|||
if (hasSingularity) {
|
||||
// Try to address singular points such that the distance between two subsequent vertices
|
||||
// are smaller than epsilon.
|
||||
Interface0DIterator v = stroke->verticesBegin();
|
||||
Interface0DIterator vnext = v;
|
||||
StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin();
|
||||
StrokeInternal::StrokeVertexIterator vnext = v;
|
||||
++vnext;
|
||||
Vec2r next((*v).getPoint2D());
|
||||
Vec2r next((*v).getPoint());
|
||||
while (!vnext.isEnd()) {
|
||||
current = next;
|
||||
next = (*vnext).getPoint2D();
|
||||
next = (*vnext).getPoint();
|
||||
if ((next - current).norm() < 1.0e-6) {
|
||||
Interface0DIterator vprevious = v;
|
||||
StrokeInternal::StrokeVertexIterator vprevious = v;
|
||||
if (!vprevious.isBegin())
|
||||
--vprevious;
|
||||
|
||||
// collect a set of overlapping vertices
|
||||
std::vector<Interface0D *> overlapping_vertices;
|
||||
std::vector<StrokeVertex *> overlapping_vertices;
|
||||
overlapping_vertices.push_back(&(*v));
|
||||
do {
|
||||
overlapping_vertices.push_back(&(*vnext));
|
||||
|
@ -1114,17 +1115,17 @@ static Stroke *createStroke(Interface1D& inter)
|
|||
++vnext;
|
||||
if (vnext.isEnd())
|
||||
break;
|
||||
next = (*vnext).getPoint2D();
|
||||
next = (*vnext).getPoint();
|
||||
} while ((next - current).norm() < 1.0e-6);
|
||||
|
||||
Vec2r target;
|
||||
bool reverse;
|
||||
if (!vnext.isEnd()) {
|
||||
target = (*vnext).getPoint2D();
|
||||
target = (*vnext).getPoint();
|
||||
reverse = false;
|
||||
}
|
||||
else if (!vprevious.isBegin()) {
|
||||
target = (*vprevious).getPoint2D();
|
||||
target = (*vprevious).getPoint();
|
||||
reverse = true;
|
||||
}
|
||||
else {
|
||||
|
@ -1132,7 +1133,7 @@ static Stroke *createStroke(Interface1D& inter)
|
|||
delete stroke;
|
||||
return NULL;
|
||||
}
|
||||
current = overlapping_vertices.front()->getPoint2D();
|
||||
current = overlapping_vertices.front()->getPoint();
|
||||
Vec2r dir(target - current);
|
||||
real dist = dir.norm();
|
||||
real len = 1.0e-3; // default offset length
|
||||
|
@ -1144,10 +1145,10 @@ static Stroke *createStroke(Interface1D& inter)
|
|||
Vec2r offset(dir * len);
|
||||
// add the offset to the overlapping vertices
|
||||
StrokeVertex *sv;
|
||||
std::vector<Interface0D *>::iterator it = overlapping_vertices.begin();
|
||||
std::vector<StrokeVertex *>::iterator it = overlapping_vertices.begin();
|
||||
if (!reverse) {
|
||||
for (int n = 1; n < nvert; n++) {
|
||||
sv = dynamic_cast<StrokeVertex*>(*it);
|
||||
sv = (*it);
|
||||
sv->setPoint(sv->getPoint() + offset * n);
|
||||
++it;
|
||||
}
|
||||
|
@ -1155,7 +1156,7 @@ static Stroke *createStroke(Interface1D& inter)
|
|||
else {
|
||||
int last = nvert - 1;
|
||||
for (int n = 0; n < last; n++) {
|
||||
sv = dynamic_cast<StrokeVertex*>(*it);
|
||||
sv = (*it);
|
||||
sv->setPoint(sv->getPoint() + offset * (last - n));
|
||||
++it;
|
||||
}
|
||||
|
|
|
@ -375,14 +375,14 @@ public:
|
|||
return _Point2d[1];
|
||||
}
|
||||
|
||||
/*! Returns the 2D point coordinates as a Vec2d */
|
||||
Vec2f getPoint ()
|
||||
/*! Returns the 2D point coordinates as a Vec2r */
|
||||
inline Vec2r getPoint() const
|
||||
{
|
||||
return Vec2f((float)point2d()[0], (float)point2d()[1]);
|
||||
return getPoint2D();
|
||||
}
|
||||
|
||||
/*! Returns the ith 2D point coordinate (i=0 or 1)*/
|
||||
inline real operator[](const int i) const
|
||||
inline real operator[](const int i) const
|
||||
{
|
||||
return _Point2d[i];
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ public:
|
|||
}
|
||||
|
||||
/*! sets the 2D x and y values */
|
||||
inline void setPoint(const Vec2f& p)
|
||||
inline void setPoint(const Vec2r& p)
|
||||
{
|
||||
_Point2d[0] = p[0];
|
||||
_Point2d[1] = p[1];
|
||||
|
|
|
@ -48,7 +48,7 @@ real Interface0D::getZ() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Geometry::Vec3f Interface0D::getPoint3D() const
|
||||
Geometry::Vec3r Interface0D::getPoint3D() const
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden");
|
||||
return 0;
|
||||
|
@ -72,7 +72,7 @@ real Interface0D::getProjectedZ() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Geometry::Vec2f Interface0D::getPoint2D() const
|
||||
Geometry::Vec2r Interface0D::getPoint2D() const
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden");
|
||||
return 0;
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
virtual real getZ() const;
|
||||
|
||||
/*! Returns the 3D point. */
|
||||
virtual Geometry::Vec3f getPoint3D() const;
|
||||
virtual Geometry::Vec3r getPoint3D() const;
|
||||
|
||||
/*! Returns the 2D x coordinate of the point. */
|
||||
virtual real getProjectedX() const;
|
||||
|
@ -98,7 +98,7 @@ public:
|
|||
virtual real getProjectedZ() const;
|
||||
|
||||
/*! Returns the 2D point. */
|
||||
virtual Geometry::Vec2f getPoint2D() const;
|
||||
virtual Geometry::Vec2r getPoint2D() const;
|
||||
|
||||
/*! Returns the FEdge that lies between this Interface0D and the Interface0D given as argument. */
|
||||
virtual FEdge *getFEdge(Interface0D&);
|
||||
|
|
|
@ -103,7 +103,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 3D point. */
|
||||
virtual Vec3f getPoint3D() const
|
||||
virtual Vec3r getPoint3D() const
|
||||
{
|
||||
return _Point3D;
|
||||
}
|
||||
|
@ -127,9 +127,9 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 2D point. */
|
||||
virtual Vec2f getPoint2D() const
|
||||
virtual Vec2r getPoint2D() const
|
||||
{
|
||||
return Vec2f((float)_Point2D.x(), (float)_Point2D.y());
|
||||
return Vec2f(_Point2D.x(), _Point2D.y());
|
||||
}
|
||||
|
||||
/*! Returns the FEdge that lies between this Svertex and the Interface0D given as argument. */
|
||||
|
|
|
@ -419,7 +419,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 3D point. */
|
||||
virtual Vec3f getPoint3D() const
|
||||
virtual Vec3r getPoint3D() const
|
||||
{
|
||||
cerr << "Warning: getPoint3D() undefined for this point" << endl;
|
||||
return _FrontSVertex->getPoint3D();
|
||||
|
@ -443,7 +443,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 2D point. */
|
||||
virtual Vec2f getPoint2D() const
|
||||
virtual Vec2r getPoint2D() const
|
||||
{
|
||||
return _FrontSVertex->getPoint2D();
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 3D point. */
|
||||
virtual Vec3f getPoint3D() const
|
||||
virtual Vec3r getPoint3D() const
|
||||
{
|
||||
return _SVertex->getPoint3D();
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ public: // Implementation of Interface0D
|
|||
}
|
||||
|
||||
/*! Returns the 2D point. */
|
||||
virtual Vec2f getPoint2D() const
|
||||
virtual Vec2r getPoint2D() const
|
||||
{
|
||||
return _SVertex->getPoint2D();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue