|
|
145120 |
|
|
|
145120 |
#include <vector></vector>
|
|
|
145120 |
|
|
|
145120 |
#include "random.h"
|
|
|
145120 |
#include "matrix.h"
|
|
|
145120 |
|
|
|
145120 |
#include "bendarea.h"
|
|
|
145120 |
|
|
|
145120 |
|
|
|
145120 |
namespace {
|
|
|
145120 |
enum BendMode {
|
|
|
145120 |
BendNone,
|
|
|
145120 |
BendRound,
|
|
|
145120 |
BendCorner
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
class ContourChunk {
|
|
|
145120 |
public:
|
|
|
145120 |
Vector p1, t0, t1;
|
|
|
145120 |
explicit ContourChunk(const Vector &p1 = Vector(), const Vector &t0 = Vector(), const Vector &t1 = Vector()):
|
|
|
145120 |
p1(p1), t0(t0), t1(t1) { }
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
class BendPoint {
|
|
|
145120 |
public:
|
|
|
145120 |
Vector p;
|
|
|
145120 |
Vector t0, t1;
|
|
|
145120 |
bool e0, e1;
|
|
|
145120 |
Real l;
|
|
|
145120 |
Real length;
|
|
|
145120 |
BendMode mode;
|
|
|
145120 |
BendPoint(): e0(), e1(), l(), length(), mode(BendNone) { }
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
class Intersection {
|
|
|
145120 |
public:
|
|
|
145120 |
Real l;
|
|
|
145120 |
BendPoint point;
|
|
|
145120 |
explicit Intersection(const Real &l = Real(), const BendPoint &point = BendPoint()):
|
|
|
145120 |
l(l), point(point) { }
|
|
|
145120 |
bool operator<(const Intersection &other) const { return l < other.l; }
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
typedef std::vector<intersection> IntersectionList;</intersection>
|
|
|
145120 |
|
|
|
145120 |
class Contour: public std::vector<contourchunk> {</contourchunk>
|
|
|
145120 |
public:
|
|
|
145120 |
void hermite_to(const Vector &p1, const Vector &t0, const Vector &t1)
|
|
|
145120 |
{ push_back( ContourChunk(p1, t0, t1) ); }
|
|
|
145120 |
void line_to(const Vector &p1) {
|
|
|
145120 |
if (empty()) {
|
|
|
145120 |
hermite_to(p1, Vector(), Vector());
|
|
|
145120 |
} else
|
|
|
145120 |
if (p1 != back().p1) {
|
|
|
145120 |
Vector t = p1 - back().p1;
|
|
|
145120 |
hermite_to(p1, t, t);
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void line(const Vector &p0, const Vector &p1)
|
|
|
145120 |
{ line_to(p0); line_to(p1); }
|
|
|
145120 |
void hermite(const Vector &p0, const Vector &p1, const Vector &t0, const Vector &t1)
|
|
|
145120 |
{ line_to(p0); hermite_to(p1, t0, t1); }
|
|
|
145120 |
void hermite(const Hermite &h)
|
|
|
145120 |
{ hermite(h.p0, h.p1, h.t0, h.t1); }
|
|
|
145120 |
|
|
|
145120 |
void put(const Context &context, bool jump = false) const {
|
|
|
145120 |
if (empty()) return;
|
|
|
145120 |
const_iterator i = begin();
|
|
|
145120 |
Hermite h(i->p1, i->p1);
|
|
|
145120 |
for(++i; i != end(); ++i) {
|
|
|
145120 |
h.p0 = h.p1;
|
|
|
145120 |
h.p1 = i->p1;
|
|
|
145120 |
h.t0 = i->t0;
|
|
|
145120 |
h.t1 = i->t1;
|
|
|
145120 |
context.hermite(h, jump);
|
|
|
145120 |
jump = false;
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
class BendContour: public std::vector<bendpoint> {</bendpoint>
|
|
|
145120 |
public:
|
|
|
145120 |
const_iterator find(const Real &length) const {
|
|
|
145120 |
if (empty()) return end();
|
|
|
145120 |
const_iterator a = begin(), b = end() - 1, c;
|
|
|
145120 |
if (!less(a->length, length)) return a;
|
|
|
145120 |
if (!less(length, b->length)) return b;
|
|
|
145120 |
while( (c = a + (b - a)/2) != a ) {
|
|
|
145120 |
if (equal(length, c->length)) return c;
|
|
|
145120 |
(length < c->length ? b : a) = c;
|
|
|
145120 |
}
|
|
|
145120 |
return c;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
const BendPoint* find_exact(const Real &length) const {
|
|
|
145120 |
const_iterator i = find(length);
|
|
|
145120 |
return i == end() || !equal(length, i->length) ? nullptr : &*i;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
BendPoint interpolate(const Real &length) const {
|
|
|
145120 |
const_iterator i = find(length);
|
|
|
145120 |
if (i == end()) return BendPoint();
|
|
|
145120 |
|
|
|
145120 |
if (equal(length, i->length)) return *i;
|
|
|
145120 |
|
|
|
145120 |
if (length < i->length) {
|
|
|
145120 |
// extarpolation before
|
|
|
145120 |
Real dlen = length - i->length;
|
|
|
145120 |
BendPoint s;
|
|
|
145120 |
s.p = i->p + i->t0.norm()*dlen;
|
|
|
145120 |
s.t0 = s.t1 = i->t0.norm();
|
|
|
145120 |
s.l = i->l + dlen;
|
|
|
145120 |
s.length = length;
|
|
|
145120 |
s.e0 = s.e1 = i->e0;
|
|
|
145120 |
return s;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
const_iterator j = i + 1;
|
|
|
145120 |
if (j == end()) {
|
|
|
145120 |
// extarpolation after
|
|
|
145120 |
Real dlen = length - i->length;
|
|
|
145120 |
BendPoint s;
|
|
|
145120 |
s.p = i->p + i->t1.norm()*dlen;
|
|
|
145120 |
s.t0 = s.t1 = i->t1.norm();
|
|
|
145120 |
s.l = i->l + dlen;
|
|
|
145120 |
s.length = length;
|
|
|
145120 |
s.e0 = s.e1 = i->e1;
|
|
|
145120 |
return s;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
// interpolation
|
|
|
145120 |
Real l = (length - i->length)/(j->length - i->length);
|
|
|
145120 |
Real dl = j->l - i->l;
|
|
|
145120 |
Hermite h(i->p, j->p, i->t1*dl, j->t0*dl);
|
|
|
145120 |
|
|
|
145120 |
BendPoint s;
|
|
|
145120 |
s.p = h.p(l);
|
|
|
145120 |
s.t0 = s.t1 = h.t(l);
|
|
|
145120 |
s.l = i->l + l*(j->l - i->l);
|
|
|
145120 |
s.length = length;
|
|
|
145120 |
s.e0 = s.e1 = (i->e1 && j->e0);
|
|
|
145120 |
|
|
|
145120 |
return s;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void half_corner(Contour &dst, const BendPoint &point, const Real &radius, bool flip, bool out) const {
|
|
|
145120 |
if (point.mode == BendNone || equal(radius, 0))
|
|
|
145120 |
return;
|
|
|
145120 |
|
|
|
145120 |
const Vector &t0 = flip ? point.t1 : point.t0;
|
|
|
145120 |
const Vector &t1 = flip ? point.t0 : point.t1;
|
|
|
145120 |
const Vector p0 = t0.perp().norm() * radius;
|
|
|
145120 |
const Vector p1 = t1.perp().norm() * radius;
|
|
|
145120 |
const Vector &p = out ? p1 : p0;
|
|
|
145120 |
const Vector ¢er = point.p;
|
|
|
145120 |
const Real rmod = fabs(radius);
|
|
|
145120 |
|
|
|
145120 |
Real d = dot( t0, t1.perp() );
|
|
|
145120 |
if (!equal(0, d) && (d*radius < 0) == flip) {
|
|
|
145120 |
if (point.mode == BendRound) {
|
|
|
145120 |
const Vector pp = (p0 + p1).norm()*rmod;
|
|
|
145120 |
const Vector ppp = (p + pp).norm()*rmod;
|
|
|
145120 |
Real k = (ppp - p).len()/rmod;
|
|
|
145120 |
if (dot(p, ppp.perp()) < 0) k = -k;
|
|
|
145120 |
if (out) {
|
|
|
145120 |
dst.line_to(center + pp);
|
|
|
145120 |
dst.hermite_to(center + ppp, pp.perp()*k, ppp.perp()*k);
|
|
|
145120 |
dst.hermite_to(center + p, ppp.perp()*k, p.perp()*k);
|
|
|
145120 |
} else {
|
|
|
145120 |
k = -k;
|
|
|
145120 |
dst.line_to(center + p);
|
|
|
145120 |
dst.hermite_to(center + ppp, p.perp()*k, ppp.perp()*k);
|
|
|
145120 |
dst.hermite_to(center + pp, ppp.perp()*k, pp.perp()*k);
|
|
|
145120 |
}
|
|
|
145120 |
} else
|
|
|
145120 |
if (point.mode == BendCorner) {
|
|
|
145120 |
Vector pp = p0 + t0*(dot(p1 - p0, t1.perp())/d);
|
|
|
145120 |
if (out) dst.line(center + pp, center + p);
|
|
|
145120 |
else dst.line(center + p, center + pp);
|
|
|
145120 |
}
|
|
|
145120 |
} else {
|
|
|
145120 |
Vector pp = (p0 + p1)*0.5;
|
|
|
145120 |
if (out) dst.line(center + pp, center + p);
|
|
|
145120 |
else dst.line(center + p, center + pp);
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void bend(Contour &dst, const Contour &src, const Matrix &matrix = Matrix()) const {
|
|
|
145120 |
if (empty() || src.empty())
|
|
|
145120 |
dst.insert(dst.end(), src.begin(), src.end());
|
|
|
145120 |
|
|
|
145120 |
Contour::const_iterator i = src.begin();
|
|
|
145120 |
Vector p0 = matrix.transform(i->p1);
|
|
|
145120 |
size_t dst_size = dst.size();
|
|
|
145120 |
|
|
|
145120 |
IntersectionList intersections;
|
|
|
145120 |
while(++i != src.end()) {
|
|
|
145120 |
Hermite h(p0, matrix.transform(i->p1), matrix.transform(i->t0, false), matrix.transform(i->t1, false));
|
|
|
145120 |
p0 = h.p1;
|
|
|
145120 |
|
|
|
145120 |
Real bends[2];
|
|
|
145120 |
int bends_count = h.bends_x(bends);
|
|
|
145120 |
Range r(h.p0.x);
|
|
|
145120 |
r.expand(h.p1.x);
|
|
|
145120 |
for(Real *i = bends, *end = i + bends_count; i != end; ++i)
|
|
|
145120 |
r.expand( Hermite::p(*i, h.p0.x, h.p1.x, h.t0.x, h.t1.x) );
|
|
|
145120 |
bool b0 = bends_count > 0, b1 = bends_count > 1;
|
|
|
145120 |
|
|
|
145120 |
for(const_iterator bi = find(r.a0); bi != end() && !less(r.a1, bi->length); ++bi) {
|
|
|
145120 |
Real roots[3];
|
|
|
145120 |
int count = h.intersections_x(roots, bi->length);
|
|
|
145120 |
for(Real *i = roots, *end = i + count; i != end; ++i) {
|
|
|
145120 |
if (b0 && equal(*i, bends[0])) b0 = false;
|
|
|
145120 |
if (b1 && equal(*i, bends[1])) b1 = false;
|
|
|
145120 |
intersections.push_back( Intersection(*i, *bi) );
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
if (b0) intersections.push_back( Intersection(bends[0], interpolate( h.p(bends[0]).x )) );
|
|
|
145120 |
if (b1) intersections.push_back( Intersection(bends[1], interpolate( h.p(bends[1]).x )) );
|
|
|
145120 |
sort(intersections.begin(), intersections.end());
|
|
|
145120 |
|
|
|
145120 |
Intersection prev(0, interpolate(h.p0.x));
|
|
|
145120 |
intersections.push_back( Intersection(1, interpolate(h.p1.x)) );
|
|
|
145120 |
|
|
|
145120 |
for(IntersectionList::const_iterator bi = intersections.begin(); bi != intersections.end(); ++bi) {
|
|
|
145120 |
const Intersection &next = *bi;
|
|
|
145120 |
if (equal(prev.l, next.l)) continue;
|
|
|
145120 |
|
|
|
145120 |
bool flip = next.point.l < prev.point.l;
|
|
|
145120 |
Real dl = next.point.l - prev.point.l;
|
|
|
145120 |
bool e0 = flip ? prev.point.e0 : prev.point.e1;
|
|
|
145120 |
bool e1 = flip ? next.point.e1 : next.point.e0;
|
|
|
145120 |
if (e0 && e1) {
|
|
|
145120 |
Vector bt0 = flip ? prev.point.t0 : prev.point.t1;
|
|
|
145120 |
Vector bt1 = flip ? next.point.t1 : next.point.t0;
|
|
|
145120 |
Hermite bh(prev.point.p, next.point.p, bt0*dl, bt1*dl);
|
|
|
145120 |
|
|
|
145120 |
Hermite src_h(h.sub(prev.l, next.l));
|
|
|
145120 |
Vector x0 = bt0.norm(), y0 = x0.perp();
|
|
|
145120 |
Vector x1 = bt1.norm(), y1 = x1.perp();
|
|
|
145120 |
Hermite dst_h(
|
|
|
145120 |
prev.point.p + y0*src_h.p0.y,
|
|
|
145120 |
next.point.p + y1*src_h.p1.y,
|
|
|
145120 |
x0*src_h.t0.x + y0*src_h.t0.y,
|
|
|
145120 |
x1*src_h.t1.x + y1*src_h.t1.y );
|
|
|
145120 |
Real k = (src_h.p1 - src_h.p0).lensqr();
|
|
|
145120 |
if (!equal(k, 0)) {
|
|
|
145120 |
k = sqrt( (dst_h.p1 - dst_h.p0).lensqr()/k );
|
|
|
145120 |
dst_h.t0 *= k;
|
|
|
145120 |
dst_h.t1 *= k;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
half_corner(dst, prev.point, src_h.p0.y, flip, true);
|
|
|
145120 |
dst.hermite(dst_h);
|
|
|
145120 |
half_corner(dst, next.point, src_h.p1.y, flip, false);
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
prev = next;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
intersections.clear();
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
if (dst_size < dst.size())
|
|
|
145120 |
dst.line_to(dst[dst_size].p1);
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void draw(const Context &context) const {
|
|
|
145120 |
if (empty()) return;
|
|
|
145120 |
|
|
|
145120 |
context->save();
|
|
|
145120 |
|
|
|
145120 |
context.set_line_width_px(10);
|
|
|
145120 |
context.set_source_rgba(Color::blue().mulalpha(0.1));
|
|
|
145120 |
|
|
|
145120 |
for(const_iterator i = begin(); i != end(); ++i) {
|
|
|
145120 |
context.move_to(i->p + i->t0);
|
|
|
145120 |
context.line_to(i->p);
|
|
|
145120 |
context.line_to(i->p + i->t1);
|
|
|
145120 |
}
|
|
|
145120 |
context->stroke();
|
|
|
145120 |
|
|
|
145120 |
context.set_source_rgba(Color::blue().mulalpha(0.25));
|
|
|
145120 |
for(const_iterator j = begin(), i = j++; j != end(); i = j++) {
|
|
|
145120 |
Real dl = j->l - i->l;
|
|
|
145120 |
context.hermite(Hermite(i->p, j->p, i->t1*dl, j->t0*dl), true);
|
|
|
145120 |
}
|
|
|
145120 |
context->stroke();
|
|
|
145120 |
|
|
|
145120 |
context->restore();
|
|
|
145120 |
}
|
|
|
145120 |
};
|
|
|
145120 |
|
|
|
145120 |
void build_contour(Contour &dst, const ActiveCurve &curve) {
|
|
|
145120 |
size_t dst_size = dst.size();
|
|
|
145120 |
for(ActiveCurve::SegIter i(curve); i; i.next())
|
|
|
145120 |
dst.hermite( i.hermite() );
|
|
|
145120 |
if (dst_size < dst.size())
|
|
|
145120 |
dst.line_to( dst[dst_size].p1 );
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void build_bend(BendContour &dst, const ActiveCurve &curve, bool round, int segments) {
|
|
|
145120 |
const Real dl = Real(1)/segments;
|
|
|
145120 |
size_t dst_size = dst.size();
|
|
|
145120 |
BendPoint bp;
|
|
|
145120 |
BendMode mode = round ? BendRound : BendCorner;
|
|
|
145120 |
|
|
|
145120 |
bp.p = curve.front().get_p();
|
|
|
145120 |
bp.e0 = bp.e1 = true;
|
|
|
145120 |
bp.l = 0;
|
|
|
145120 |
bp.length = 0;
|
|
|
145120 |
bp.mode = BendNone;
|
|
|
145120 |
dst.push_back( bp );
|
|
|
145120 |
|
|
|
145120 |
int index = 0;
|
|
|
145120 |
for(ActiveCurve::SegIter i(curve); i; i.next()) {
|
|
|
145120 |
Hermite h = i.hermite();
|
|
|
145120 |
|
|
|
145120 |
dst.back().p = h.p0;
|
|
|
145120 |
dst.back().t1 = h.t0;
|
|
|
145120 |
|
|
|
145120 |
Real l0 = index;
|
|
|
145120 |
Real l = dl;
|
|
|
145120 |
bp.mode = BendNone;
|
|
|
145120 |
for(int k = 2; k < segments; ++k, l += dl) {
|
|
|
145120 |
Vector p = h.p(l);
|
|
|
145120 |
bp.l = l0 + l;
|
|
|
145120 |
bp.length += (p - bp.p).len();
|
|
|
145120 |
bp.p = p;
|
|
|
145120 |
bp.t0 = bp.t1 = h.t(l);
|
|
|
145120 |
dst.push_back( bp );
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
bp.l = ++index;
|
|
|
145120 |
bp.length += (h.p1 - bp.p).len();
|
|
|
145120 |
bp.p = h.p1;
|
|
|
145120 |
bp.t0 = h.t1;
|
|
|
145120 |
bp.mode = mode;
|
|
|
145120 |
dst.push_back( bp );
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
BendPoint &first = dst[dst_size];
|
|
|
145120 |
BendPoint &last = dst.back();
|
|
|
145120 |
if (curve.loop) {
|
|
|
145120 |
first.mode = mode;
|
|
|
145120 |
first.t0 = last.t0;
|
|
|
145120 |
last.t1 = first.t1;
|
|
|
145120 |
first.e0 = last.e1 = false;
|
|
|
145120 |
} else {
|
|
|
145120 |
first.t0 = first.t1;
|
|
|
145120 |
last.t1 = last.t0;
|
|
|
145120 |
last.mode = BendNone;
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
|
|
|
145120 |
|
|
|
145120 |
|
|
|
145120 |
BendArea::BendArea():
|
|
|
145120 |
p0(new ActivePoint(Vector(100, 100), Color::blue())),
|
|
|
145120 |
p1(new ActivePoint(Vector(900, 100), Color::blue()))
|
|
|
145120 |
{
|
|
|
145120 |
set_size_request(1000, 900);
|
|
|
145120 |
|
|
|
145120 |
add_point(p0);
|
|
|
145120 |
add_point(p1);
|
|
|
145120 |
|
|
|
145120 |
// generate src curve
|
|
|
145120 |
Vector b0 = p0->position - Vector(20, 80);
|
|
|
145120 |
Vector b1 = p1->position + Vector(20, 0);
|
|
|
145120 |
Vector pp(b0.x, b1.y);
|
|
|
145120 |
while(true) {
|
|
|
145120 |
Vector pt0 = pp + Vector(-50, 0); //rnd::vector(pp.x - 20, b0.y, pp.x + 20, b1.y);
|
|
|
145120 |
Vector pt1 = pp + Vector( 50, 0); //rnd::vector(pp.x - 20, b0.y, pp.x + 20, b1.y);
|
|
|
145120 |
|
|
|
145120 |
src_curve.push_back(ActiveCurvePoint(pp, pt0 - pp, pt1 - pp));
|
|
|
145120 |
src_curve.back().add_to(*this);
|
|
|
145120 |
|
|
|
145120 |
if (!less(pp.x, b1.x)) break;
|
|
|
145120 |
pp = Vector(pp.x + 60, 0.5*(b0.y + b1.y)); //rnd::vector(pp.x + 20, b0.y, pp.x + 100, b1.y);
|
|
|
145120 |
if (!less(pp.x, b1.x)) pp = b1;
|
|
|
145120 |
}
|
|
|
145120 |
src_curve.set_tail_tangents_visible();
|
|
|
145120 |
|
|
|
145120 |
// generate dst curve
|
|
|
145120 |
b0.x = p0->position.x;
|
|
|
145120 |
b0.y = p0->position.y + 200;
|
|
|
145120 |
b1.x = p1->position.x;
|
|
|
145120 |
b1.y = 780;
|
|
|
145120 |
Vector bt(100, 100);
|
|
|
145120 |
dst_curve.loop = true;
|
|
|
145120 |
for(int i = 0; i < 5; ++i) {
|
|
|
145120 |
dst_curve.push_back(ActiveCurvePoint(rnd::vector(b0, b1), rnd::vector(-bt, bt), rnd::vector(-bt, bt)));
|
|
|
145120 |
dst_curve.back().add_to(*this);
|
|
|
145120 |
}
|
|
|
145120 |
dst_curve.set_tail_tangents_visible();
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void BendArea::on_point_move(const ActivePoint::Handle &point, const Vector&oldposition, const Vector &newposition) {
|
|
|
145120 |
src_curve.on_point_move(point, oldposition, newposition);
|
|
|
145120 |
dst_curve.on_point_move(point, oldposition, newposition);
|
|
|
145120 |
if (point == p0 || point == p1)
|
|
|
145120 |
p0->position.y = p1->position.y = newposition.y;
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
void BendArea::on_draw_content(const Context &context) {
|
|
|
145120 |
context->save();
|
|
|
145120 |
|
|
|
145120 |
context.set_line_width_px(1);
|
|
|
145120 |
context.set_source_rgba(Color::blue());
|
|
|
145120 |
context.move_to(p0->position);
|
|
|
145120 |
context.line_to(p1->position);
|
|
|
145120 |
context->stroke();
|
|
|
145120 |
|
|
|
145120 |
if (!src_curve.empty()) {
|
|
|
145120 |
context.set_source_rgba(Color::gray().mulalpha(0.5));
|
|
|
145120 |
src_curve.put(context);
|
|
|
145120 |
context->close_path();
|
|
|
145120 |
context->fill();
|
|
|
145120 |
|
|
|
145120 |
if (!dst_curve.empty()) {
|
|
|
145120 |
Contour src_contour;
|
|
|
145120 |
BendContour bend;
|
|
|
145120 |
Contour dst_contour;
|
|
|
145120 |
|
|
|
145120 |
build_contour(src_contour, src_curve);
|
|
|
145120 |
build_bend(bend, dst_curve, false, 16);
|
|
|
145120 |
|
|
|
145120 |
bend.draw(context);
|
|
|
145120 |
|
|
|
145120 |
Real dst_length = bend.back().length;
|
|
|
145120 |
Real src_length = p1->position.x - p0->position.x;
|
|
|
145120 |
if (!equal(src_length, 0) && !equal(dst_length, 0)) {
|
|
|
145120 |
Real kx = dst_length/src_length;
|
|
|
145120 |
Real ky = 1;
|
|
|
145120 |
Matrix m( kx, 0, 0,
|
|
|
145120 |
0, ky, 0,
|
|
|
145120 |
-kx*p0->position.x, -ky*p0->position.y, 1 );
|
|
|
145120 |
bend.bend(dst_contour, src_contour, m);
|
|
|
145120 |
|
|
|
145120 |
dst_contour.put(context, true);
|
|
|
145120 |
context->close_path();
|
|
|
145120 |
context->fill_preserve();
|
|
|
145120 |
context.set_source_rgba(Color::blue());
|
|
|
145120 |
context->stroke();
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
}
|
|
|
145120 |
|
|
|
145120 |
context->restore();
|
|
|
145120 |
|
|
|
145120 |
src_curve.draw(context);
|
|
|
145120 |
dst_curve.draw(context);
|
|
|
145120 |
}
|
|
|
145120 |
|