From a411696b123665bef070467183860deff279a05e Mon Sep 17 00:00:00 2001 From: Jaeun Choi Date: Thu, 19 Jul 2018 19:22:19 +0900 Subject: [PATCH] vector: implement vpathmesure Change-Id: I562df481e72b4e356821b1a44b7749c29ea0b1ca --- src/vector/vpathmesure.cpp | 302 ++++++++++++++++++++++++++++++++++++++++++++- src/vector/vpathmesure.h | 4 + 2 files changed, 304 insertions(+), 2 deletions(-) diff --git a/src/vector/vpathmesure.cpp b/src/vector/vpathmesure.cpp index cabbe42..52e93e8 100644 --- a/src/vector/vpathmesure.cpp +++ b/src/vector/vpathmesure.cpp @@ -1,10 +1,308 @@ #include"vpathmesure.h" +#include"vbezier.h" V_BEGIN_NAMESPACE -class VPathMesureData +struct VPathMesureData { - VPath *path; + void setPath(const VPath &path) { mPath = path; } + VPath& getPath() { return mPath; } + VPath mPath; }; V_END_NAMESPACE + +static const struct VPathMesureData shared_empty = {VPath()}; + +VPathMesure::~VPathMesure() +{ +} + +VPathMesure::VPathMesure() + : d(const_cast(&shared_empty)) +{ +} + +VPathMesure::VPathMesure(const VPath *p, bool foceClose) +{ +} + +void VPathMesure::setStart(float pos) +{ + VPath &path = d->getPath(); + const std::vector &elm = path.elements(); + const std::vector &pts = path.points(); + std::vector len; + + std::vector elm_copy; + + int i = 0, idx = 0; + float totlen = 0.0; + float startlen = 0.0; + bool cut = false; + + for (auto e : elm) { + elm_copy.push_back(e); + switch(e) { + case VPath::Element::MoveTo: + break; + case VPath::Element::LineTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + + VBezier b = VBezier::fromPoints(p0, p0, p, p); + totlen += b.length(); + len.push_back(b.length()); + break; + } + case VPath::Element::CubicTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + VPointF p1 = pts[i++]; + VPointF p2 = pts[i++]; + + VBezier b = VBezier::fromPoints(p0, p, p1, p2); + totlen += b.length(); + len.push_back(b.length()); + + break; + } + case VPath::Element::Close: + break; + } + } + + startlen = totlen * (pos / 100); + i = 0; + path.reset(); + + for (auto e : elm_copy) { + switch(e) { + case VPath::Element::MoveTo: + { + VPointF p = pts[i++]; + path.moveTo(p.x(), p.y()); + break; + } + case VPath::Element::LineTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + + if (!cut) + { + if (len.at(idx) < startlen) + { + startlen -= len.at(idx); + } + else if (len.at(idx) == startlen) + { + path.moveTo(p.x(), p.y()); + cut = true; + } + else + { + VBezier b, bleft; + float ratio = (startlen/len.at(idx)); + b = VBezier::fromPoints(p0, p0, p, p); + b.parameterSplitLeft(ratio, &bleft); + + path.moveTo(b.pt1().x(), b.pt1().y()); + path.lineTo(b.pt4().x(), b.pt4().y()); + cut = true; + } + idx++; + } + else + { + path.lineTo(p.x(), p.y()); + } + break; + } + case VPath::Element::CubicTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + VPointF p1 = pts[i++]; + VPointF p2 = pts[i++]; + + if (!cut) + { + if (len.at(idx) < startlen) + { + startlen -= len.at(idx); + } + else if (len.at(idx) == startlen) + { + path.moveTo(p2.x(), p2.y()); + cut = true; + } + else + { + VBezier b, bleft; + float ratio = (startlen/len.at(idx)); + b = VBezier::fromPoints(p0, p, p1, p2); + b.parameterSplitLeft(ratio, &bleft); + + path.moveTo(b.pt1().x(), b.pt1().y()); + path.cubicTo(b.pt2().x(), b.pt2().y(), + b.pt3().x(), b.pt3().y(), + b.pt4().x(), b.pt4().y()); + cut = true; + } + idx++; + } + else + { + path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y()); + } + break; + } + case VPath::Element::Close: + break; + } + } +} + +void VPathMesure::setEnd(float pos) +{ + VPath &path = d->getPath(); + const std::vector &elm = path.elements(); + const std::vector &pts = path.points(); + std::vector len; + + std::vector elm_copy; + + int i = 0, idx = 0; + float totlen = 0.0; + float endlen = 0.0; + bool cut = false; + + for (auto e : elm) { + elm_copy.push_back(e); + switch(e) { + case VPath::Element::MoveTo: + break; + case VPath::Element::LineTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + + VBezier b = VBezier::fromPoints(p0, p0, p, p); + totlen += b.length(); + len.push_back(b.length()); + break; + } + case VPath::Element::CubicTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + VPointF p1 = pts[i++]; + VPointF p2 = pts[i++]; + + VBezier b = VBezier::fromPoints(p0, p, p1, p2); + totlen += b.length(); + len.push_back(b.length()); + + break; + } + case VPath::Element::Close: + break; + } + } + + endlen = totlen * (pos / 100); + i = 0; + path.reset(); + + for (auto e : elm_copy) { + switch(e) { + case VPath::Element::MoveTo: + { + VPointF p = pts[i++]; + path.moveTo(p.x(), p.y()); + break; + } + case VPath::Element::LineTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + + if (!cut) + { + if (len.at(idx) < endlen) + { + path.lineTo(p.x(), p.y()); + endlen -= len.at(idx); + } + else if (len.at(idx) == endlen) + { + path.lineTo(p.x(), p.y()); + cut = true; + } + else + { + VBezier b, bleft; + float ratio = (endlen/len.at(idx)); + b = VBezier::fromPoints(p0, p0, p, p); + b.parameterSplitLeft(ratio, &bleft); + + path.lineTo(bleft.pt4().x(), bleft.pt4().y()); + cut = true; + } + idx++; + } + break; + } + case VPath::Element::CubicTo: + { + VPointF p0 = pts[i - 1]; + VPointF p = pts[i++]; + VPointF p1 = pts[i++]; + VPointF p2 = pts[i++]; + + if (!cut) + { + if (len.at(idx) < endlen) + { + path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y()); + endlen -= len.at(idx); + } + else if (len.at(idx) == endlen) + { + path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y()); + cut = true; + } + else + { + VBezier b, bleft; + float ratio = (endlen/len.at(idx)); + b = VBezier::fromPoints(p0, p, p1, p2); + b.parameterSplitLeft(ratio, &bleft); + + path.cubicTo(bleft.pt2().x(), bleft.pt2().y(), + bleft.pt3().x(), bleft.pt3().y(), + bleft.pt4().x(), bleft.pt4().y()); + cut = true; + } + idx++; + } + break; + } + case VPath::Element::Close: + break; + } + } +} + +void VPathMesure::setPath(const VPath &path) +{ + d->setPath(path); +} + +VPath VPathMesure::getPath() +{ + return d->getPath(); +} diff --git a/src/vector/vpathmesure.h b/src/vector/vpathmesure.h index 0a97fc1..88fc9fd 100644 --- a/src/vector/vpathmesure.h +++ b/src/vector/vpathmesure.h @@ -13,6 +13,10 @@ public: VPathMesure(); VPathMesure(const VPath *path, bool foceClose); int getLength() const; + void setPath(const VPath &path); + VPath getPath(); + void setStart(float pos); + void setEnd(float pos); private: VPathMesureData *d; }; -- 2.7.4