-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
updating writers to allow user to get Blob data directly
- Loading branch information
1 parent
a7943ad
commit c95108b
Showing
8 changed files
with
362 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>Streamlines Animation Example</title> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script> | ||
<script src="../dist/stitch.global.js"></script> | ||
<script>window.Stitch || document.write('<script src="https://unpkg.com/@stitchables/stitchjs/dist/stitch.global.js">\x3C/script>')</script> | ||
</head> | ||
<body> | ||
<script> | ||
|
||
|
||
class QT { | ||
constructor(bb, cap) { | ||
this.bb = bb; | ||
this.cap = cap; | ||
this.ps = []; | ||
this.cs = []; | ||
this.div = false; | ||
} | ||
sub() { | ||
for (let i of [-1, 1]) for (let j of [-1, 1]) { | ||
this.cs.push(new QT(new BB([this.bb.p[0] + i * 0.5 * this.bb.d[0], this.bb.p[1] + j * 0.5 * this.bb.d[1]], [0.5 * this.bb.d[0], 0.5 * this.bb.d[1]]), this.cap)); | ||
} | ||
for (let p of this.ps) for (let c of this.cs) if (c.bb.cont(p)) c.ins(p); | ||
this.ps = []; | ||
this.div = true; | ||
} | ||
ins(p) { | ||
if (!this.bb.cont(p.p)) return false; | ||
if (this.ps.length < this.cap && !this.div) { | ||
this.ps.push(p); | ||
return true; | ||
} else { | ||
if (!this.div) this.sub(); | ||
for (let c of this.cs) if (c.ins(p)) return true; | ||
} | ||
} | ||
q(rng, f) { | ||
if (!f) f = []; | ||
if (!this.bb.inter(rng)) return; | ||
else { | ||
for (let p of this.ps) if (rng.cont(p)) f.push(p); | ||
if (this.div) for (let c of this.cs) c.q(rng, f); | ||
} | ||
return f; | ||
} | ||
} | ||
|
||
class BB { | ||
constructor(p, d) { | ||
this.p = p; | ||
this.d = d; | ||
} | ||
cont(p) { | ||
for (let i of [0, 1]) if (p[i] < this.p[i] - this.d[i] || p[i] >= this.p[i] + this.d[i]) return false; | ||
return true; | ||
} | ||
inter(bb) { | ||
for (let i of [0, 1]) if (bb.p[i] - bb.d[i] > this.p[i] + this.d[i] || bb.p[i] + bb.d[i] < this.p[i] - this.d[i]) return false; | ||
return true; | ||
} | ||
} | ||
|
||
class ESS { | ||
constructor(d, vf, sf, dsf) { | ||
this.d = d; | ||
this.vf = vf; | ||
this.sf = sf; | ||
this.dsf = dsf; | ||
this.qt = new QT(new BB([0.5 * d[0], 0.5 * d[1]], [0.5 * d[0], 0.5 * d[1]]), 4); | ||
this.sl = []; | ||
} | ||
rst() { | ||
this.qt = new QT(new BB([0.5 * this.d[0], 0.5 * this.d[1]], [0.5 * this.d[0], 0.5 * this.d[1]]), 4); | ||
this.sl = []; | ||
} | ||
csl(s) { | ||
if (this.cp(s) || this.sl.length == 0) { | ||
let tl = this.cssl(s); | ||
this.sl.push(tl); | ||
for (let p of tl) this.qt.ins({p: p, i: this.sl.length - 1}); | ||
for (let p of tl) { | ||
let o = this.vf(p); | ||
o = this.nrm(o); | ||
o = this.rot(o); | ||
o = this.mult(o, this.sf(p)); | ||
this.csl([p[0] + o[0], p[1] + o[1]]); | ||
this.csl([p[0] - o[0], p[1] - o[1]]); | ||
} | ||
} | ||
return this.sl; | ||
} | ||
cssl(s) { | ||
let tqt = new QT(new BB([0.5 * this.d[0], 0.5 * this.d[1]], [0.5 * this.d[0], 0.5 * this.d[1]]), 4); | ||
let l = 0; | ||
tqt.ins({p: s, l: l}); | ||
let tl = [s]; | ||
let fl = false; | ||
while(true) { | ||
let lp = tl[tl.length - 1]; | ||
let d = this.vf(lp); | ||
if (fl) d = this.mult(d, -1); | ||
let np = [lp[0] + d[0], lp[1] + d[1]]; | ||
// let di = dist(0, 0, d[0], d[1]); | ||
let di = Math.sqrt(d[0] * d[0] + d[1] * d[1]); | ||
if (!this.cp(np, tqt, di, l, lp)) { | ||
if (!fl) { | ||
tl.reverse(); | ||
l = 0; | ||
fl = true; | ||
} else return tl; | ||
} else { | ||
tl.push(np); | ||
l += fl ? -di : di; | ||
tqt.ins({p: np, l: l}); | ||
} | ||
} | ||
} | ||
// check point | ||
cp(p, tqt, di, l, pp) { | ||
if (!this.cb(p)) return false; | ||
if (di) if (!this.csn(di)) return false; | ||
if (!this.csp(p, pp)) return false; | ||
if (pp) if (!this.csi(tqt, l, p)) return false; | ||
return true; | ||
} | ||
// check boundary | ||
cb(p) { | ||
for (let i of [0, 1]) if (p[i] < 0 || p[i] > this.d[i]) return false; | ||
return true; | ||
} | ||
// check sink | ||
csn(di) { return di > 0.001; } | ||
// check separation | ||
csp(p, pp) { | ||
let s = this.sf(p); | ||
let ds = 1; | ||
if (pp) ds = this.dsf(p); | ||
let ns = this.qt.q(new BB(p, [s, s])); | ||
// for (let n of ns) if (dist(p[0], p[1], n.p[0], n.p[1]) < ds * s) return false; | ||
for (let n of ns) if (Math.sqrt((n.p[0] - p[0]) * (n.p[0] - p[0]) + (n.p[1] - p[1]) * (n.p[1] - p[1])) < ds * s) return false; | ||
return true; | ||
} | ||
csi(tqt, l, p) { | ||
let s = this.sf(p); | ||
let ns = tqt.q(new BB(p, [s, s])); | ||
for (let n of ns) { | ||
// let cd = dist(p[0], p[1], n.p[0], n.p[1]); | ||
let cd = Math.sqrt((n.p[0] - p[0]) * (n.p[0] - p[0]) + (n.p[1] - p[1]) * (n.p[1] - p[1])); | ||
if (cd < s && Math.abs(l - n.l) > s) return false; | ||
} | ||
return true; | ||
} | ||
nrm(v) { | ||
// let l = dist(0, 0, v[0], v[1]); | ||
let l = Math.sqrt(v[0] * v[0] + v[1] * v[1]); | ||
return [v[0] / l, v[1] / l]; | ||
} | ||
rot(v) { return [v[1], -v[0]]; } | ||
mult(v, m) { return [m * v[0], m * v[1]]; } | ||
getSl() { | ||
let output = []; | ||
for (let sli = 0; sli < this.sl.length; sli++) { | ||
let sl = this.sl[sli]; | ||
let sld = []; | ||
for (let p of sl) { | ||
let sf = this.sf(p); | ||
let dsf = this.dsf(p); | ||
let ns = this.qt.q(new BB(p, [sf, sf])); | ||
// let minDist = min(min(p[0], this.d[0] - p[0]), min(p[1], this.d[1] - p[1])); | ||
let minDist = Infinity; | ||
for (let n of ns) { | ||
if (sli != n.i) { | ||
// let currDist = dist(p[0], p[1], n.p[0], n.p[1]); | ||
let currDist = Math.sqrt((n.p[0] - p[0]) * (n.p[0] - p[0]) + (n.p[1] - p[1]) * (n.p[1] - p[1])) | ||
if (currDist < minDist) minDist = currDist; | ||
} | ||
} | ||
let tCoeff = minDist >= sf ? 1 : (minDist - sf * dsf) / (sf - sf * dsf); | ||
sld.push({x: p[0], y: p[1], t: tCoeff}); | ||
} | ||
output.push(sld); | ||
} | ||
return output; | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
let frameCount = 50; | ||
let [w, h] = [1000, 1000]; | ||
let patterns = []; | ||
for (let f = 0; f < frameCount; f++) { | ||
let pattern = new Stitch.Core.Pattern(w, h); | ||
let scn = function(px, py, sx, sy, omi, oma) { | ||
let x = 0.25 * (px + 10000) / sx; | ||
let y = 0.25 * (py + 10000) / sy; | ||
let z = 0.2 * Math.cos(2 * Math.PI * f / frameCount) + 100; | ||
let w = 0.2 * Math.sin(2 * Math.PI * f / frameCount) + 100; | ||
return Stitch.Math.Utils.map(Stitch.Math.noise(x, y, z, w), 0, 1, omi, oma); | ||
} | ||
let vf = function(p) { | ||
let a = scn(p[0], p[1], 0.3 * w, 0.3 * h, 0, 4 * Math.PI); | ||
let r = 0.003 * Math.min(w, h); | ||
let o = Stitch.Math.Utils.map(f, 0, frameCount, 0, Math.PI); | ||
// let o = 0; | ||
return [r * Math.cos(a + o), r * Math.sin(a + o)]; | ||
}; | ||
let sf = function(p) { return 0.03 * Math.min(w, h); } | ||
let dsf = function(p) { return 0.5; } | ||
let ess = new ESS([w, h], vf, sf, dsf); | ||
for (let x = 0; x < w; x += 10) { | ||
for (let y = 0; y < h; y += 10) { | ||
ess.csl([x, y]); | ||
} | ||
} | ||
let sld = ess.getSl(); | ||
|
||
let thread = pattern.addThread(0, 0, 0); | ||
for (let sl of sld) { | ||
// let polyline = new Stitch.Math.Polyline(false); | ||
// for (let p of sl) { | ||
// polyline.addVertex(p.x, p.y); | ||
// } | ||
// thread.addRun(new Stitch.Runs.Run(polyline, 1.5)); | ||
if (sl.length > 3) { | ||
let classicSatin = new Stitch.Runs.ClassicSatin(1); | ||
for (let i = 1; i < sl.length - 1; i++) { | ||
let prev = new Stitch.Math.Vector(sl[i - 1].x, sl[i - 1].y); | ||
let curr = new Stitch.Math.Vector(sl[i - 0].x, sl[i - 0].y); | ||
let next = new Stitch.Math.Vector(sl[i + 1].x, sl[i + 1].y); | ||
let n = curr.subtract(prev).add(next.subtract(curr)).divide(2) | ||
.rotate(0.5 * Math.PI).normalized(); | ||
classicSatin.addVector(curr.add(n.multiply(8 * sl[i].t * sl[i].t + 3))); | ||
classicSatin.addVector(curr.subtract(n.multiply(8 * sl[i].t * sl[i].t + 3))); | ||
} | ||
thread.addRun(classicSatin); | ||
} | ||
} | ||
patterns.push(pattern); | ||
} | ||
|
||
let svg = Stitch.Graphics.getSvg(patterns[0], window.innerWidth, window.innerHeight); | ||
svg.setAttribute('style', 'margin: auto; position: absolute; inset: 0;'); | ||
document.body.append(svg); | ||
|
||
function animate() { | ||
c++; | ||
svg.remove(); | ||
svg = Stitch.Graphics.getSvg(patterns[c % frameCount], window.innerWidth, window.innerHeight); | ||
svg.setAttribute('style', 'margin: auto; position: absolute; inset: 0;'); | ||
document.body.append(svg); | ||
requestAnimationFrame(() => { setTimeout(animate, 120); }); | ||
} | ||
let c = 0; | ||
animate(); | ||
|
||
const [dstZip, pesZip] = [new JSZip(), new JSZip()]; | ||
for (let i = 0; i < frameCount; i++) { | ||
const wMm = Stitch.Math.Utils.inToMm(3.8); | ||
const hMm = Stitch.Math.Utils.inToMm(3.8); | ||
const dstData = Stitch.IO.getData(patterns[i], wMm, hMm, `essAnimation-${i}.dst`); | ||
const pesData = Stitch.IO.getData(patterns[i], wMm, hMm, `essAnimation-${i}.pes`); | ||
dstZip.file(`essAnimation-${i}.dst`, dstData, { binary: true }); | ||
pesZip.file(`essAnimation-${i}.pes`, pesData, { binary: true }); | ||
} | ||
|
||
window.addEventListener("keydown", async (e) => { | ||
if (e.code === "KeyD") { | ||
console.log(dstZip); | ||
dstZip.generateAsync({ type: "blob" }) | ||
.then((content) => { | ||
const a = document.createElement('a'); | ||
a.href = window.URL.createObjectURL(content); | ||
a.download = 'essAnimationDst.zip'; | ||
a.click(); | ||
}); | ||
} else if (e.code === "KeyP") { | ||
pesZip.generateAsync({ type: "blob" }) | ||
.then((content) => { | ||
const a = document.createElement('a'); | ||
a.href = URL.createObjectURL(content); | ||
a.download = 'essAnimationPes.zip'; | ||
a.click(); | ||
}); | ||
} | ||
}); | ||
|
||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import { IResolvedStitches } from '../../Core/Pattern'; | ||
|
||
export interface IWriter { | ||
write: (resolvedStitches: IResolvedStitches, filename: string) => void; | ||
write: ( | ||
resolvedStitches: IResolvedStitches, | ||
filename: string, | ||
) => (number | string | Uint8Array)[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.