#include "line.h"
void lineTranspose(Vertex *l, int cols) {
int cnt = cols*LN_SEGS+1;
for(int i = 0; i < cnt; ++i) {
Vertex *v = &l[i];
v->p = vtranspose(v->p);
v->t = vtranspose(v->t);
}
}
void lineGenH(Vertex *l, int cols, double y, double cellw, double cellh, double jitter, double depth) {
if (cols <= 0) return;
double kx = cellh < cellw ? cellh/cellw : 1.0;
double ky = cellw < cellh ? cellw/cellh : 1.0;
int cnt = cols*LN_SEGS+1;
for(int i = 0; i < cnt; ++i)
l[i] = (Vertex){ {i*cellw/LN_SEGS, y}, {}, 1 };
if (jitter) for(int i = 1; i < cnt-1; ++i) {
l[i].p.x += randTwo()*kx*jitter*cellw/2;
l[i].p.y += randTwo()*ky*jitter*cellh;
l[i].w += randOne()*0.25;
}
for(int c = 0; c < cols; ++c) {
double j = jitter ? randTwo()*(1-kx)/3 : 0;
l[c*LN_SEGS+1].p.x += ( 0.3 - kx/6 + j)*cellw;
l[c*LN_SEGS+2].p.x += ( 0.1 - kx/6 + j)*cellw;
l[c*LN_SEGS+3].p.x += (-0.1 + kx/6 + j)*cellw;
l[c*LN_SEGS+4].p.x += (-0.3 + kx/6 + j)*cellw;
double d = randSign()*depth*ky*cellh;
l[c*LN_SEGS+2].p.y += d;
l[c*LN_SEGS+3].p.y += d;
}
Vec b = l[0].p, e = l[cnt-1].p;
b.x -= 1/3.0; e.x += 1/3.0;
for(int i = 0; i < cnt; ++i) {
Vertex *v = &l[i];
Vec p0 = i ? (v-1)->p : b;
Vec p1 = i+1<cnt ? (v+1)->p : e;
v->t = vmul(vsub(p1, p0), v->w/2);
}
}
void lineGenV(Vertex *l, int rows, double x, double cellw, double cellh, double jitter, double depth) {
lineGenH(l, rows, x, cellh, cellw, jitter, depth);
lineTranspose(l, rows);
}
void linePut(Vertex *l, int cells, int levels) {
int cnt = cells*LN_SEGS;
if (cnt > 0) {
for(int i = 1; i <= cnt; ++i) {
Vertex v0 = l[i-1];
Vertex v1 = l[i];
cubicto(
v0.p.x, v0.p.y,
v0.p.x + v0.t.x/3, v0.p.y + v0.t.y/3,
v1.p.x - v1.t.x/3, v1.p.y - v1.t.y/3,
v1.p.x, v1.p.y,
levels );
}
} else {
for(int i = -1; i >= cnt; --i) {
Vertex v0 = l[i+1];
Vertex v1 = l[i];
cubicto(
v0.p.x, v0.p.y,
v0.p.x - v0.t.x/3, v0.p.y - v0.t.y/3,
v1.p.x + v1.t.x/3, v1.p.y + v1.t.y/3,
v1.p.x, v1.p.y,
levels );
}
}
}
void lineDraw(Vertex *l, int cells, int levels) {
if (!cells) return;
moveTo(l->p.x, l->p.y);
linePut(l, cells, levels);
strokePath();
}