vector: implement vpathmesure

Change-Id: I562df481e72b4e356821b1a44b7749c29ea0b1ca
This commit is contained in:
Jaeun Choi 2018-07-19 19:22:19 +09:00 committed by Hermet Park
parent f2bf8eabc9
commit a411696b12
2 changed files with 304 additions and 2 deletions

View File

@ -1,10 +1,308 @@
#include"vpathmesure.h" #include"vpathmesure.h"
#include"vbezier.h"
V_BEGIN_NAMESPACE 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 V_END_NAMESPACE
static const struct VPathMesureData shared_empty = {VPath()};
VPathMesure::~VPathMesure()
{
}
VPathMesure::VPathMesure()
: d(const_cast<VPathMesureData*>(&shared_empty))
{
}
VPathMesure::VPathMesure(const VPath *p, bool foceClose)
{
}
void VPathMesure::setStart(float pos)
{
VPath &path = d->getPath();
const std::vector<VPath::Element> &elm = path.elements();
const std::vector<VPointF> &pts = path.points();
std::vector<float> len;
std::vector<VPath::Element> 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<VPath::Element> &elm = path.elements();
const std::vector<VPointF> &pts = path.points();
std::vector<float> len;
std::vector<VPath::Element> 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();
}

View File

@ -13,6 +13,10 @@ public:
VPathMesure(); VPathMesure();
VPathMesure(const VPath *path, bool foceClose); VPathMesure(const VPath *path, bool foceClose);
int getLength() const; int getLength() const;
void setPath(const VPath &path);
VPath getPath();
void setStart(float pos);
void setEnd(float pos);
private: private:
VPathMesureData *d; VPathMesureData *d;
}; };