diff --git a/src/fineditors/outlineeditor/contourcalculator.cpp b/src/fineditors/outlineeditor/contourcalculator.cpp index 4d477b4..15e61d9 100644 --- a/src/fineditors/outlineeditor/contourcalculator.cpp +++ b/src/fineditors/outlineeditor/contourcalculator.cpp @@ -35,28 +35,29 @@ using namespace fineditors; -ContourCalculator::ContourCalculator(qreal percContourHeight, QPainterPath *outline, QPainterPath *profile, - QPainterPath *thickness, QPainterPath *result, bool fast) +ContourCalculator::ContourCalculator(qreal percContourHeight, EditablePath *outline, EditablePath *profile, EditablePath *thickness, QPainterPath *result, bool fast) { - _percContourHeight = percContourHeight; _outline = outline; _profile = profile; _thickness = thickness; + + + _percContourHeight = percContourHeight; _result = result; if (fast) { - _sectionCount = 20; - _resolution = 200; - _tTol = 0.002; - _fTol = 0.01; + _sectionCount = 200; + _resolution = 500; + _tTol = 0.0001; + _fTol = 0.001; } else { - _sectionCount = 150; - _resolution = 400; - _tTol = 0.0001; - _fTol = 0.001; + _sectionCount = 1000; + _resolution = 2000; + _tTol = 0.00001; + _fTol = 0.0001; } } @@ -67,13 +68,15 @@ void ContourCalculator::run() qreal thicknessArray[_sectionCount]; sampleThickess(sectionHeightArray, thicknessArray); + // create the pathfunctors + f_yValueAtPercentEPath yOutline(_outline); + f_yValueAtPercentEPath yProfile(_profile); + // find the top of the outline - f_yValueAtPercent yOutline(_outline); qreal t_top = 0.5; // start value qreal y_top = hrlib::Brent::local_min(0, 1, _tTol, yOutline, t_top); // glomin isn't finding a correct top // find dimensions of the profile - f_yValueAtPercent yProfile(_profile); qreal t_profileTop = 0.3; // start value qreal y_profileTop = hrlib::Brent::local_min(0, 1, _tTol, yProfile, t_profileTop); qreal profileLength = _profile->pointAtPercent(1).x(); diff --git a/src/fineditors/outlineeditor/contourcalculator.h b/src/fineditors/outlineeditor/contourcalculator.h index 1a21a8c..9c49b86 100644 --- a/src/fineditors/outlineeditor/contourcalculator.h +++ b/src/fineditors/outlineeditor/contourcalculator.h @@ -24,28 +24,31 @@ #define CONTOURCALCULATOR_H #include "hrlibfwd/qtfwd.h" +#include "patheditorfwd/patheditorfwd.h" #include +using namespace patheditor; + namespace fineditors { class ContourCalculator : public QRunnable { public: - explicit ContourCalculator(qreal percContourHeight, QPainterPath *outline, QPainterPath *profile, - QPainterPath *thickness, QPainterPath *result, bool fast = false); + explicit ContourCalculator(qreal percContourHeight, EditablePath *outline, EditablePath *profile, + EditablePath *thickness, QPainterPath *result, bool fast = false); virtual void run(); virtual ~ContourCalculator(); - private: + private: enum SplineFunction { bSpline, overhauser }; qreal _percContourHeight; - QPainterPath *_outline; - QPainterPath *_profile; - QPainterPath *_thickness; + EditablePath *_outline; + EditablePath *_profile; + EditablePath *_thickness; QPainterPath *_result; int _sectionCount; diff --git a/src/fineditors/outlineeditor/pathfunctors.h b/src/fineditors/outlineeditor/pathfunctors.h index 17191d8..ddb322a 100644 --- a/src/fineditors/outlineeditor/pathfunctors.h +++ b/src/fineditors/outlineeditor/pathfunctors.h @@ -23,19 +23,42 @@ #ifndef PATHFUNCTORS_H #define PATHFUNCTORS_H -#include "hrlib/math/brent.hpp" #include "hrlibfwd/qtfwd.h" +#include "hrlib/math/brent.hpp" +#include "editablepath.h" + namespace fineditors { - class f_yValueAtPercent : public hrlib::func_base + class f_yValueAtPercentPPath : public hrlib::func_offset_base { private: QPainterPath *_path; qreal _offset; public: - explicit f_yValueAtPercent(QPainterPath *path, qreal offset = 0){ + explicit f_yValueAtPercentPPath(QPainterPath *path, qreal offset = 0){ + _path = path; + _offset = offset; + } + + virtual qreal operator ()(qreal t){ + return _path->pointAtPercent(t).y() - _offset; + } + + virtual void setOffset(qreal offset){ + _offset = offset; + } + }; + + class f_yValueAtPercentEPath : public hrlib::func_offset_base + { + private: + patheditor::EditablePath *_path; + qreal _offset; + + public: + explicit f_yValueAtPercentEPath(patheditor::EditablePath *path, qreal offset = 0){ _path = path; _offset = offset; } @@ -44,7 +67,7 @@ namespace fineditors return _path->pointAtPercent(t).y() - _offset; } - void setOffset(qreal offset){ + virtual void setOffset(qreal offset){ _offset = offset; } }; diff --git a/src/fineditors/outlineeditor/thicknesscontours.cpp b/src/fineditors/outlineeditor/thicknesscontours.cpp index dc110e6..4805e27 100644 --- a/src/fineditors/outlineeditor/thicknesscontours.cpp +++ b/src/fineditors/outlineeditor/thicknesscontours.cpp @@ -35,6 +35,10 @@ ThicknessContours::ThicknessContours(QGraphicsItem *parent) : { _nextDetailed = false; + _outline = 0; + _profile = 0; + _thickness = 0; + int numOfContours = std::max(_tPool.maxThreadCount(), 3); qreal increment = qreal(1) / qreal(numOfContours+1); qreal thickness = 0; @@ -49,7 +53,7 @@ ThicknessContours::ThicknessContours(QGraphicsItem *parent) : void ThicknessContours::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*unused*/, QWidget * /*unused*/) { - if (!_outline.isNull()) + if (_outline != 0) { int min = 0; int max = 255; @@ -57,7 +61,7 @@ void ThicknessContours::paint(QPainter *painter, const QStyleOptionGraphicsItem int increment = 0; painter->setBrush(QColor(min, 0, max, a)); - painter->drawPath(*_outline); + painter->drawPath(*(_outline->painterPath())); calcContours(); @@ -79,7 +83,7 @@ void ThicknessContours::paint(QPainter *painter, const QStyleOptionGraphicsItem QRectF ThicknessContours::boundingRect() const { - if (_outline.isNull()) + if (_outline == 0) { QRectF retVal; return retVal; @@ -91,20 +95,20 @@ QRectF ThicknessContours::boundingRect() const void ThicknessContours::onOutlineChange(EditablePath *sender) { _fastCalc = !(sender->released()); - _outline = sender->painterPath(); + _outline = sender; } void ThicknessContours::onProfileChange(EditablePath *sender) { _fastCalc = !(sender->released()); - _profile = sender->painterPath(); + _profile = sender; this->scene()->update(boundingRect()); } void ThicknessContours::onThicknessChange(EditablePath *sender) { _fastCalc = !(sender->released()); - _thickness = sender->painterPath(); + _thickness = sender; this->scene()->update(boundingRect()); } @@ -119,7 +123,7 @@ void ThicknessContours::calcContours() QSharedPointer path(new QPainterPath()); _contours.append(path); - ContourCalculator calc(thickness, _outline.data(), _profile.data(), _thickness.data(), path.data(), _fastCalc); + ContourCalculator calc(thickness, _outline, _profile, _thickness, path.data(), _fastCalc); calc.run(); } #endif @@ -129,7 +133,7 @@ void ThicknessContours::calcContours() QSharedPointer path(new QPainterPath()); _contours.append(path); - _tPool.start(new ContourCalculator(thickness, _outline.data(), _profile.data(), _thickness.data(), path.data(), _fastCalc)); + _tPool.start(new ContourCalculator(thickness, _outline, _profile, _thickness, path.data(), _fastCalc)); } _tPool.waitForDone(); #endif @@ -138,13 +142,13 @@ void ThicknessContours::calcContours() bool ThicknessContours::profilesSet() { - if (_outline.isNull()) + if (_outline == 0) return false; - if (_profile.isNull()) + if (_profile == 0) return false; - if (_thickness.isNull()) + if (_thickness == 0) return false; return true; diff --git a/src/fineditors/outlineeditor/thicknesscontours.h b/src/fineditors/outlineeditor/thicknesscontours.h index 1eec46e..bca2453 100644 --- a/src/fineditors/outlineeditor/thicknesscontours.h +++ b/src/fineditors/outlineeditor/thicknesscontours.h @@ -53,9 +53,9 @@ namespace fineditors bool _fastCalc; QThreadPool _tPool; - QSharedPointer _outline; - QSharedPointer _profile; - QSharedPointer _thickness; + EditablePath* _outline; + EditablePath* _profile; + EditablePath* _thickness; QList _contourThicknesses; QList > _contours; diff --git a/src/hrlib/math/brent.hpp b/src/hrlib/math/brent.hpp index fbd8b2d..d300a60 100644 --- a/src/hrlib/math/brent.hpp +++ b/src/hrlib/math/brent.hpp @@ -16,6 +16,12 @@ class func_base{ virtual qreal operator() (qreal) = 0; }; +class func_offset_base : public func_base{ +public: + virtual qreal operator() (qreal) = 0; + virtual void setOffset(qreal offset) = 0; +}; + class monicPoly : public func_base { public: std::vector coeff; diff --git a/src/patheditor/cubicbezier.cpp b/src/patheditor/cubicbezier.cpp index 325b8cf..36e0a02 100644 --- a/src/patheditor/cubicbezier.cpp +++ b/src/patheditor/cubicbezier.cpp @@ -69,6 +69,22 @@ QList > CubicBezier::controlPoints() return _controlPoints; } +QPointF CubicBezier::pointAtPercent(qreal t) +{ + // X(t) = (1-t)^3 * X0 + 3*(1-t)^2 * t * X1 + 3*(1-t) * t^2 * X2 + t^3 * X3 + + qreal oneMt = 1-t; + qreal tSq = t*t; + qreal tCu = tSq * t; + + qreal xAtPercent = (oneMt*oneMt*oneMt) * startPoint()->x() + 3 * (oneMt*oneMt) * t * _cPoint1->x() + + 3 * oneMt * tSq * _cPoint2->x() + tCu * endPoint()->x(); + qreal yAtPercent = (oneMt*oneMt*oneMt) * startPoint()->y() + 3 * (oneMt*oneMt) * t * _cPoint1->y() + + 3 * oneMt * tSq * _cPoint2->y() + tCu * endPoint()->y(); + + return QPointF(xAtPercent, yAtPercent); +} + QRectF CubicBezier::boundingRect() const { return _boundingRect; diff --git a/src/patheditor/cubicbezier.h b/src/patheditor/cubicbezier.h index d97a8f6..58eb1cc 100644 --- a/src/patheditor/cubicbezier.h +++ b/src/patheditor/cubicbezier.h @@ -47,6 +47,7 @@ namespace patheditor // implementing PathItem QList > controlPoints(); + virtual QPointF pointAtPercent(qreal t); // Implementing QGraphicsItem QRectF boundingRect() const; diff --git a/src/patheditor/editablepath.cpp b/src/patheditor/editablepath.cpp index eabf8c8..eda1c4b 100644 --- a/src/patheditor/editablepath.cpp +++ b/src/patheditor/editablepath.cpp @@ -119,6 +119,23 @@ QSharedPointer EditablePath::painterPath() return _painterPath; } +QPointF EditablePath::pointAtPercent(qreal t) +{ + int pathItemCount = _pathItemList.count(); + qreal itemRange = 1/qreal(pathItemCount); + + int item = 0; + while (t > itemRange) + { + t -= itemRange; + item++; + } + + t = t/itemRange; + + return _pathItemList[item]->pointAtPercent(t); +} + bool EditablePath::released() { return _released; diff --git a/src/patheditor/editablepath.h b/src/patheditor/editablepath.h index 0ce7a60..68eaa56 100644 --- a/src/patheditor/editablepath.h +++ b/src/patheditor/editablepath.h @@ -25,7 +25,7 @@ #include "patheditorfwd/patheditorfwd.h" -#include +#include #include "pathitem.h" #include "pathsettings.h" @@ -58,6 +58,8 @@ namespace patheditor */ QSharedPointer painterPath(); + QPointF pointAtPercent(qreal t); + bool released(); virtual ~EditablePath() {} @@ -77,7 +79,7 @@ namespace patheditor QSharedPointer _painterPath; - QLinkedList > _pathItemList; + QList > _pathItemList; void connectPoints(PathItem *pathItem); }; diff --git a/src/patheditor/line.cpp b/src/patheditor/line.cpp index 5c7f734..52d2bd8 100644 --- a/src/patheditor/line.cpp +++ b/src/patheditor/line.cpp @@ -40,6 +40,11 @@ QList > Line::controlPoints() return _controlPoints; } +QPointF Line::pointAtPercent(qreal t) +{ + return (*endPoint() - *startPoint()) * t + *startPoint(); +} + QRectF Line::boundingRect() const { return _boundingRect; diff --git a/src/patheditor/line.h b/src/patheditor/line.h index 5f1a198..9447f3c 100644 --- a/src/patheditor/line.h +++ b/src/patheditor/line.h @@ -40,6 +40,7 @@ namespace patheditor // implementing PathItem QList > controlPoints(); + virtual QPointF pointAtPercent(qreal t); // Implementing QGraphicsItem QRectF boundingRect() const; diff --git a/src/patheditor/pathitem.h b/src/patheditor/pathitem.h index ebf8dba..f6ce489 100644 --- a/src/patheditor/pathitem.h +++ b/src/patheditor/pathitem.h @@ -67,6 +67,11 @@ namespace patheditor virtual void paintPathItem(PathSettings *settings, QPainterPath *totalPainterPath, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) = 0; + // + // Custom path calculation (preferably faster than using QPainterPath) + // + virtual QPointF pointAtPercent(qreal t) = 0; + virtual ~PathItem() {} private: diff --git a/src/version_autogen.h b/src/version_autogen.h index 482961b..8459377 100644 --- a/src/version_autogen.h +++ b/src/version_autogen.h @@ -5,7 +5,7 @@ #ifndef VERSION_AUTOGEN_H #define VERSION_AUTOGEN_H -#define BUILD_NUMBER 127 -#define COMMIT_HASH "a95010d24e94c042a23e6a2f7710803e46e0ed9e" +#define BUILD_NUMBER 128 +#define COMMIT_HASH "291e758411fa0f67fa164f35af0e0a027dc32338" #endif // VERSION_AUTOGEN_H