class Vec2 { constructor(x, y) { this.x = x; this.y = y; } add(v) { return new Vec2(this.x + v.x, this.y + v.y); } sub(v) { return new Vec2(this.x - v.x, this.y - v.y); } mult(v) { return new Vec2(this.x * v.x, this.y * v.y); } div(v) { return new Vec2(this.x / v.x, this.y / v.y); } scale(k) { return new Vec2(this.x * k, this.y * k); } length() { return Math.sqrt(this.x * this.x + this.y * this.y); } lengthSq() { return (this.x * this.x + this.y * this.y); } normalize() { return this.scale(1.0 / this.length()); } eq(v) { return Math.abs(this.x - v.x) <= Vec2.EPSILON && Math.abs(this.y - v.y <= Vec2.EPSILON); } cloneDeeply() { return new Vec2(this.x, this.y); } rotate(rad) { return new Vec2(this.x * Math.cos(rad) - this.y * Math.sin(rad), this.x * Math.sin(rad) + this.y * Math.cos(rad)); } static normalize(v) { return v.normalize(); } static dot(v1, v2) { return v1.x * v2.x + v1.y * v2.y; } static distance(v1, v2) { const l = v1.sub(v2); return Math.sqrt(l.x * l.x + l.y * l.y); } static get EPSILON() { return 0.00001; } getUniformArray() { return [this.x, this.y]; } } let maxStep = 2; class Tri { /** * @param {Vec2} a * @param {Vec2} b */ constructor(a, b) { const r = (1.0 + sqrt(5)) / (2 * (2 + sqrt(5))); this.r = r; this.A = new Vec2(0, 0); this.B = new Vec2(1, 0); this.C = new Vec2(0.5, sqrt(3) * 0.5); this.D = new Vec2(r, 0); this.E = new Vec2(1 - r, 0); this.F = new Vec2(1 - r * 0.5, sqrt(3) * 0.5 * r); this.G = new Vec2((1 - r) * 0.5 + r, (1 - r) * sqrt(3) * 0.5); this.H = new Vec2((1 - r) * 0.5, (1 - r) * sqrt(3) * 0.5); this.I = new Vec2(r * 0.5, sqrt(3) * 0.5 * r); this.J = new Vec2(r * 0.5 + 1 - 2 * r, sqrt(3) * 0.5 * r); this.K = new Vec2(r + (1 - 2 * r) * 0.5, (1 - 2 * r) * sqrt(3) * 0.5); this.L = new Vec2(1 - r * 0.5 - (1 - 2 * r), sqrt(3) * 0.5 * r); this.originalPoints = [this.A, this.B, this.C, this.D, this.E, this.F, this.G, this.H, this.I, this.J, this.K, this.L]; this.scale = Vec2.distance(a, b); const d = b.sub(a) this.rad = Math.atan2(d.y, d.x); this.nA = a; this.nB = b; this.nC = this.C.rotate(this.rad).scale(this.scale).add(this.nA);; this.nD = this.D.rotate(this.rad).scale(this.scale).add(this.nA); this.nE = this.E.rotate(this.rad).scale(this.scale).add(this.nA); this.nF = this.F.rotate(this.rad).scale(this.scale).add(this.nA); this.nG = this.G.rotate(this.rad).scale(this.scale).add(this.nA); this.nH = this.H.rotate(this.rad).scale(this.scale).add(this.nA); this.nI = this.I.rotate(this.rad).scale(this.scale).add(this.nA); this.nJ = this.J.rotate(this.rad).scale(this.scale).add(this.nA); this.nK = this.K.rotate(this.rad).scale(this.scale).add(this.nA); this.nL = this.L.rotate(this.rad).scale(this.scale).add(this.nA); this.points = [this.nA, this.nB, this.nC, this.nD, this.nE, this.nF, this.nG, this.nH, this.nI, this.nJ, this.nK, this.nL]; const triangles = [ [this.nA, this.nD, this.nI], [this.nC, this.nH, this.nG], [this.nF, this.nE, this.nB], [this.nJ, this.nK, this.nL] ]; this.center = this.nA.add(this.nB).add(this.nC).scale(1/3); this.area = (this.nA.x * (this.nB.y - this.nC.y) + this.nB.x * (this.nC.y - this.nA.y) + this.nC.x * (this.nA.y - this.nB.y)) * 0.5; } static area(a, b, c) { return (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y))* 0.5; } triangle(a, b, c, t) { triangle(a.x, a.y, b.x, b.y, c.x, c.y); } quad(a, b, c, d, t) { quad(a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y); } draw(i) { if(i % 3 === 0) { fill(0); //stroke(1) this.triangle(this.nA, this.nD, this.nI, 0); this.triangle(this.nC, this.nH, this.nG, 0); this.triangle(this.nF, this.nE, this.nB, 0); this.triangle(this.nJ, this.nK, this.nL); //stroke(0); fill(1); this.quad(this.nH, this.nI, this.nD, this.nK); fill(1); this.quad(this.nD, this.nE, this.nF, this.nL); fill(1); this.quad(this.nH, this.nJ, this.nF, this.nG); } else if(i % 3 === 1) { fill(1); //stroke(0) this.triangle(this.nA, this.nD, this.nI, 0); this.triangle(this.nC, this.nH, this.nG, 0); this.triangle(this.nF, this.nE, this.nB, 0); this.triangle(this.nJ, this.nK, this.nL); fill(0); //stroke(1); this.quad(this.nH, this.nI, this.nD, this.nK); //stroke(0); fill(1); this.quad(this.nD, this.nE, this.nF, this.nL); fill(0); //stroke(0); this.quad(this.nH, this.nJ, this.nF, this.nG); } else if (i % 3 === 2){ fill(1); //stroke(1) this.triangle(this.nA, this.nD, this.nI, 0); this.triangle(this.nC, this.nH, this.nG, 0); fill(0); this.triangle(this.nF, this.nE, this.nB, 0); fill(0, 1, 0) this.triangle(this.nJ, this.nK, this.nL); //stroke(0); fill(0, 0, 1); this.quad(this.nH, this.nI, this.nD, this.nK); fill(1); this.quad(this.nD, this.nE, this.nF, this.nL); fill(0, 0, 1); this.quad(this.nH, this.nJ, this.nF, this.nG); } } drawBase() { fill(1); this.triangle(this.nA, this.nB, this.nC); } rotate(rad) { const preA = this.nA.cloneDeeply(); this.nA = this.nA.sub(preA).rotate(rad).add(preA); this.nB = this.nB.sub(preA).rotate(rad).add(preA); this.nC = this.nC.sub(preA).rotate(rad).add(preA); this.nD = this.nD.sub(preA).rotate(rad).add(preA); this.nE = this.nE.sub(preA).rotate(rad).add(preA); this.nF = this.nF.sub(preA).rotate(rad).add(preA); this.nG = this.nG.sub(preA).rotate(rad).add(preA); this.nH = this.nH.sub(preA).rotate(rad).add(preA); this.nI = this.nI.sub(preA).rotate(rad).add(preA); this.nJ = this.nJ.sub(preA).rotate(rad).add(preA); this.nK = this.nK.sub(preA).rotate(rad).add(preA); this.nL = this.nL.sub(preA).rotate(rad).add(preA); return this; } translate(v) { this.nA = this.nA.add(v); this.nB = this.nB.add(v); this.nC = this.nC.add(v); this.nD = this.nD.add(v); this.nE = this.nE.add(v); this.nF = this.nF.add(v); this.nG = this.nG.add(v); this.nH = this.nH.add(v); this.nI = this.nI.add(v); this.nJ = this.nJ.add(v); this.nK = this.nK.add(v); this.nL = this.nL.add(v); return this; } translated(v) { const newTri = new Tri(new Vec2(0, 0), new Vec2(0, 0)); newTri.nA = this.nA.add(v); newTri.nB = this.nB.add(v); newTri.nC = this.nC.add(v); newTri.nD = this.nD.add(v); newTri.nE = this.nE.add(v); newTri.nF = this.nF.add(v); newTri.nG = this.nG.add(v); newTri.nH = this.nH.add(v); newTri.nI = this.nI.add(v); newTri.nJ = this.nJ.add(v); newTri.nK = this.nK.add(v); newTri.nL = this.nL.add(v); return newTri; } next() { return [ new Tri(this.nA, this.nD, this.nI), new Tri(this.nH, this.nG, this.nC), new Tri(this.nE, this.nB, this.nF), new Parallelogram(this.nJ, this.nF), new Parallelogram(this.nI, this.nD), new Parallelogram(this.nE, this.nF), new Tri(this.nJ, this.nK) ]; } } class Parallelogram { /** * @param {Vec2} a * @param {Vec2} b * @param {Vec2} d */ constructor(a, b, d) { const t = (1 + sqrt(5)) * 0.5; const r = 1 / (t + 1); this.r = r; this.A = new Vec2(0, 0); this.B = new Vec2(1, 0); this.C = new Vec2(-1/(2 * t) + 1, sqrt(3) / (2 * t)); this.D = new Vec2(-1/(2 * t), sqrt(3) / (2 * t)); this.E = new Vec2(r, 0); this.G = this.C.sub(new Vec2(r, 0)); this.F = new Vec2(-1/(2 * t) + 1 + r / (2 * t),sqrt(3) * (1 - r) / (2 * t)); this.H = new Vec2(-r/(2 * t), sqrt(3) * r / (2 * t)); this.I = this.H.add(new Vec2(r / t, 0)) this.J = this.E.add(this.C.sub(this.F)) this.K = this.J.add(new Vec2(r / t, 0)) this.L = this.F.add(this.H.sub(this.I)) this.M = this.G.add(this.F.sub(this.C)); this.N = this.M.sub(new Vec2(r / t, 0)); this.originalPoints = [this.A, this.B, this.C, this.D, this.E, this.F, this.G, this.H, this.I, this.J, this.K, this.L]; this.scale = Vec2.distance(a, b); const ab = b.sub(a); this.rad = Math.atan2(ab.y, ab.x); this.nA = a.cloneDeeply(); this.nB = b; this.nC = this.C.rotate(this.rad).scale(this.scale).add(this.nA); this.nD = this.D.rotate(this.rad).scale(this.scale).add(this.nA); this.nE = this.E.rotate(this.rad).scale(this.scale).add(this.nA); this.nF = this.F.rotate(this.rad).scale(this.scale).add(this.nA); this.nG = this.G.rotate(this.rad).scale(this.scale).add(this.nA); this.nH = this.H.rotate(this.rad).scale(this.scale).add(this.nA); this.nI = this.I.rotate(this.rad).scale(this.scale).add(this.nA); this.nJ = this.J.rotate(this.rad).scale(this.scale).add(this.nA); this.nK = this.K.rotate(this.rad).scale(this.scale).add(this.nA); this.nL = this.L.rotate(this.rad).scale(this.scale).add(this.nA); this.nM = this.M.rotate(this.rad).scale(this.scale).add(this.nA); this.nN = this.N.rotate(this.rad).scale(this.scale).add(this.nA); this.center = this.nA.add(this.nC).add(this.nB).add(this.nD).scale(1/4); this.area = Tri.area(this.nA, this.nB, this.nD) + Tri.area(this.nD, this.nB, this.nC); } triangle(a, b, c, t) { triangle(a.x, a.y, b.x, b.y, c.x, c.y); } quad(a, b, c, d, t) { quad(a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y); } draw(i) { if(i % 3 === 0) { fill(0, 1, 0); //stroke(255); this.quad(this.nA, this.nE, this.nJ, this.nH); fill(0); this.quad(this.nG, this.nM, this.nF, this.nC); fill(0); this.quad(this.nG, this.nN, this.nE, this.nK); //stroke(0); fill(1); this.quad(this.nD, this.nH, this.nI, this.nG); fill(1); this.quad(this.nE, this.nB, this.nF, this.nL); fill(1, 0, 0); this.triangle(this.nN, this.nI, this.nJ); fill(1, 0, 0) this.triangle(this.nM, this.nK, this.nL); } else if(i % 3 === 1) { fill(0); //stroke(255); this.quad(this.nA, this.nE, this.nJ, this.nH); fill(0); this.quad(this.nG, this.nM, this.nF, this.nC); //stroke(0); fill(1); this.quad(this.nG, this.nN, this.nE, this.nK); fill(1, 0, 0); this.quad(this.nD, this.nH, this.nI, this.nG); fill(1); this.quad(this.nE, this.nB, this.nF, this.nL); fill(0, 0, 0); this.triangle(this.nN, this.nI, this.nJ); fill(0, 0, 0) this.triangle(this.nM, this.nK, this.nL); } else if(i % 3 === 2) { fill(0); //stroke(255); this.quad(this.nA, this.nE, this.nJ, this.nH); fill(1, 0, 0); this.quad(this.nG, this.nM, this.nF, this.nC); //stroke(0); fill(1); this.quad(this.nG, this.nN, this.nE, this.nK); fill(1, 0, 0); this.quad(this.nD, this.nH, this.nI, this.nG); fill(1); this.quad(this.nE, this.nB, this.nF, this.nL); fill(1); this.triangle(this.nN, this.nI, this.nJ); fill(0, 0, 0) this.triangle(this.nM, this.nK, this.nL); } } drawBase() { this.quad(this.nA, this.nB, this.nC, this.nD); } rotate(rad) { const preA = this.nA.cloneDeeply(); this.nA = this.nA.sub(preA).rotate(rad).add(preA); this.nB = this.nB.sub(preA).rotate(rad).add(preA); this.nC = this.nC.sub(preA).rotate(rad).add(preA); this.nD = this.nD.sub(preA).rotate(rad).add(preA); this.nE = this.nE.sub(preA).rotate(rad).add(preA); this.nF = this.nF.sub(preA).rotate(rad).add(preA); this.nG = this.nG.sub(preA).rotate(rad).add(preA); this.nH = this.nH.sub(preA).rotate(rad).add(preA); this.nI = this.nI.sub(preA).rotate(rad).add(preA); this.nJ = this.nJ.sub(preA).rotate(rad).add(preA); this.nK = this.nK.sub(preA).rotate(rad).add(preA); this.nL = this.nL.sub(preA).rotate(rad).add(preA); this.nM = this.nM.sub(preA).rotate(rad).add(preA); this.nN = this.nN.sub(preA).rotate(rad).add(preA); return this; } translate(v) { this.nA = this.nA.add(v); this.nB = this.nB.add(v); this.nC = this.nC.add(v); this.nD = this.nD.add(v); this.nE = this.nE.add(v); this.nF = this.nF.add(v); this.nG = this.nG.add(v); this.nH = this.nH.add(v); this.nI = this.nI.add(v); this.nJ = this.nJ.add(v); this.nK = this.nK.add(v); this.nL = this.nL.add(v); this.nM = this.nM.add(v); this.nN = this.nN.add(v); return this; } translated(v) { const newP = new Parallelogram(new Vec2(0, 0), new Vec2(0, 2), new Vec2(0, 0)); newP.nA = this.nA.add(v); newP.nB = this.nB.add(v); newP.nC = this.nC.add(v); newP.nD = this.nD.add(v); newP.nE = this.nE.add(v); newP.nF = this.nF.add(v); newP.nG = this.nG.add(v); newP.nH = this.nH.add(v); newP.nI = this.nI.add(v); newP.nJ = this.nJ.add(v); newP.nK = this.nK.add(v); newP.nL = this.nL.add(v); newP.nM = this.nM.add(v); newP.nN = this.nN.add(v); return newP; } next() { return [ new Parallelogram(this.nA, this.nE), new Parallelogram(this.nN, this.nE), new Parallelogram(this.nM, this.nF), new TrapezoidA(this.nI, this.nG), new TrapezoidA(this.nL, this.nE), new Tri(this.nK, this.nL), new Tri(this.nI, this.nJ, this.nK) ] } } class TrapezoidA { constructor(a, b) { this.baseP = new Parallelogram(a, b); this.topTri = new Tri(this.baseP.nD, this.baseP.nC); this.center = this.baseP.nA.add(this.baseP.nB).add(this.topTri.nA).add(this.topTri.nC).scale(1/4); this.area = this.topTri.area + this.baseP.area; } triangle(a, b, c) { triangle(a.x, a.y, b.x, b.y, c.x, c.y); } quad(a, b, c, d) { quad(a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y); } drawBase() { this.quad(this.baseP.nA, this.baseP.nB, this.topTri.nC, this.topTri.nA); } draw(i) { if(i % 3 === 0) { // 下部 fill(1); // para this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(0); this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(1);// trapezoid -> ZD this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(1);// trapezoid -> ZT this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(1, 0, 0) this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 // parallelogram fill(1, 0, 0); this.quad(this.topTri.nH, this.topTri.nI, this.topTri.nD, this.topTri.nK); fill(0, 1, 0); this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(1);// trapezoid -> ZD this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(1, 0, 0); this.triangle(this.topTri.nA, this.topTri.nD, this.topTri.nI); fill(0) this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); // 上部と底部にまたがるtrapezoid fill(1);// trapezoid -> ZD this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } else if(i % 3 === 1) { // 下部 fill(0, 1, 0); // para this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(0); this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(0);// trapezoid -> ZD this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(1);// trapezoid -> ZT this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(1, 0, 0) this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); fill(0, 1, 0) this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 // parallelogram fill(1); this.quad(this.topTri.nH, this.topTri.nI, this.topTri.nD, this.topTri.nK); fill(1); this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(1);// trapezoid -> ZD this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(1, 0, 0); this.triangle(this.topTri.nA, this.topTri.nD, this.topTri.nI); fill(0) this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); // 上部と底部にまたがるtrapezoid fill(1);// trapezoid -> ZD this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } else if(i % 3 === 2) { // 下部 fill(1); // para this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(0); this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(0, 1, 0);// trapezoid -> ZD this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(1);// trapezoid -> ZT this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(1, 0, 0) this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); fill(1) this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 // parallelogram fill(0, 0, 1); this.quad(this.topTri.nH, this.topTri.nI, this.topTri.nD, this.topTri.nK); fill(0); this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(1, 0, 0);// trapezoid -> ZD this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(1, 0, 0); this.triangle(this.topTri.nA, this.topTri.nD, this.topTri.nI); fill(0, 0, 1) this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); // 上部と底部にまたがるtrapezoid fill(1);// trapezoid -> ZD this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } } rotate(rad) { const origin = this.baseP.nA.cloneDeeply(); const prevBasePnD = this.baseP.nD.cloneDeeply(); this.baseP = this.baseP.translate(origin.scale(-1)).rotate(rad).translate(origin); this.topTri = this.topTri.translate(prevBasePnD.scale(-1)).rotate(rad).translate(this.baseP.nD); return this; } translate(v) { this.baseP.translate(v); this.topTri.translate(v); return this; } translated(v) { const newT = new TrapezoidA(new Vec2(0, 0), new Vec2(0, 0)); newT.baseP = this.baseP.translated(v); newT.topTri = this.topTri.translated(v); return newT; } next() { return [ new Parallelogram(this.baseP.nA, this.baseP.nE), new Parallelogram(this.baseP.nN, this.baseP.nE), new TrapezoidA(this.baseP.nI, this.baseP.nG), new TrapezoidB(this.baseP.nL, this.baseP.nE), new Tri(this.baseP.nK, this.baseP.nL), new Tri(this.baseP.nI, this.baseP.nJ, this.baseP.nK), new TrapezoidA(this.baseP.nM, this.baseP.nF), new Tri(this.topTri.nA, this.topTri.nD, this.topTri.nI), new TrapezoidA(this.topTri.nJ, this.topTri.nF), new Parallelogram(this.topTri.nI, this.topTri.nD), new Parallelogram(this.topTri.nE, this.topTri.nF), new Tri(this.topTri.nJ, this.topTri.nK) ]; } } class TrapezoidB { constructor(a, b) { this.baseP = new Parallelogram(a, b, null, null); this.topTri = new Tri(this.baseP.nD, this.baseP.nC); this.center = this.baseP.nA.add(this.baseP.nB).add(this.topTri.nA).add(this.topTri.nC).scale(1/4); this.area = this.topTri.area + this.baseP.area; } triangle(a, b, c) { triangle(a.x, a.y, b.x, b.y, c.x, c.y); } quad(a, b, c, d) { quad(a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y); } drawBase() { this.quad(this.baseP.nA, this.baseP.nB, this.topTri.nC, this.topTri.nA); } draw(i) { if(i % 3 === 0) { // 下部 fill(0); this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(1); // trapezoid this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(1);// trapezoid this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(0); // parallelogram this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(1, 0, 0); this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); fill(0, 0, 1); this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 fill(1); // trapezoid ZD this.quad(this.topTri.nA, this.topTri.nD, this.topTri.nK, this.topTri.nH) fill(1, 0, 0); this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); fill(0); // para this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(0, 1, 0); // trapezoid ZT this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(0); // 上部と底部にまたがるtrapezoid this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } else if (i % 3 === 1){ // 下部 fill(1); this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(1, 0, 0); // trapezoid this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(0,0,1);// trapezoid this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(0); // parallelogram this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(1); this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 fill(1); // trapezoid ZD this.quad(this.topTri.nA, this.topTri.nD, this.topTri.nK, this.topTri.nH) fill(1, 0, 0); this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); fill(0); // para this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(1); // trapezoid ZT this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(1); // 上部と底部にまたがるtrapezoid this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } else if (i % 3 === 2){ // 下部 fill(0); this.quad(this.baseP.nA, this.baseP.nE, this.baseP.nJ, this.baseP.nH); fill(1, 0, 0); // trapezoid this.quad(this.baseP.nD, this.baseP.nH, this.baseP.nI, this.baseP.nG); fill(1);// trapezoid this.quad(this.baseP.nE, this.baseP.nB, this.baseP.nF, this.baseP.nL); fill(0, 1, 0); // parallelogram this.quad(this.baseP.nG, this.baseP.nN, this.baseP.nE, this.baseP.nK); fill(1); this.triangle(this.baseP.nN, this.baseP.nI, this.baseP.nJ); fill(0, 0, 1); this.triangle(this.baseP.nM, this.baseP.nK, this.baseP.nL); // 上部 fill(1); // trapezoid ZD this.quad(this.topTri.nA, this.topTri.nD, this.topTri.nK, this.topTri.nH) fill(1, 0, 0); this.triangle(this.topTri.nJ, this.topTri.nK, this.topTri.nL); fill(0); // para this.quad(this.topTri.nD, this.topTri.nE, this.topTri.nF, this.topTri.nL); fill(1); // trapezoid ZT this.quad(this.topTri.nF, this.topTri.nC, this.topTri.nH, this.topTri.nJ); fill(0); // 上部と底部にまたがるtrapezoid this.quad(this.topTri.nE, this.baseP.nM, this.baseP.nF, this.topTri.nF); } } rotate(rad) { const origin = this.baseP.nA.cloneDeeply(); const prevBasePnD = this.baseP.nD.cloneDeeply(); this.baseP = this.baseP.translate(origin.scale(-1)).rotate(rad).translate(origin); this.topTri = this.topTri.translate(prevBasePnD.scale(-1)).rotate(rad).translate(this.baseP.nD); return this; } translate(v) { this.baseP.translate(v); this.topTri.translate(v); return this; } translated(v) { const newT = new TrapezoidB(new Vec2(0, 0), new Vec2(0, 0)); newT.baseP = this.baseP.translated(v); newT.topTri = this.topTri.translated(v); return newT; } next() { return [ new Parallelogram(this.baseP.nA, this.baseP.nE), new Parallelogram(this.baseP.nN, this.baseP.nE), new TrapezoidA(this.baseP.nI, this.baseP.nG), new TrapezoidB(this.baseP.nL, this.baseP.nE), new Tri(this.baseP.nK, this.baseP.nL), new Tri(this.baseP.nI, this.baseP.nJ, this.baseP.nK), new TrapezoidA(this.topTri.nK, this.topTri.nH), new Parallelogram(this.topTri.nE, this.topTri.nF), new Tri(this.topTri.nJ, this.topTri.nK), // 接合部 new TrapezoidA(this.baseP.nM, this.baseP.nF), // 頂点 new TrapezoidB(this.topTri.nJ, this.topTri.nF), ]; } } let level0; let level1 = []; let level2 = []; //let level3 = []; let level3 = [[], [], []]; let level4 = [[], [], []]; let level5 = [[], [], []]; let l3, l4; function setup() { const w = 1920; const h = 1080 createCanvas(windowWidth, windowHeight); background(100); translate(0, height); const s = 1000; scale(s, -s); strokeWeight(0.01/s); noStroke(); level0 = new Tri(new Vec2(0, 0), new Vec2(1, 0)); //t.draw(); level1 = level0.next(); for(const ll of level1) { if(ll.center.y > level0.center.y) { ll.dir = 'top' } else if(ll.center.x < level0.center.x) { ll.dir = 'left' } else { ll.dir = 'right'; } } let level2Tmp = []; for(const ll of level1) { level2Tmp = level2Tmp.concat(ll.next()); } for(const ll of level2Tmp) { if(ll.center.y > level0.center.y) { ll.dir = 'top' } else if(ll.center.x < level0.center.x) { ll.dir = 'left' } else { ll.dir = 'right'; } level2.push(ll); // if(ll.area > 1 / s) { // level2.push(ll); // } } let level3Tmp = []; for(const ll of level2) { level3Tmp = level3Tmp.concat(ll.next()); } l3 = level3Tmp; for(const ll of level3Tmp) { if(ll.center.y > level0.center.y) { ll.dir = 'top' level3[0].push(ll); } else if(ll.center.x < level0.center.x) { ll.dir = 'left' level3[1].push(ll); } else { ll.dir = 'right'; level3[2].push(ll); } } let level4Tmp = [] for(const ll of level3Tmp) { if(ll.area < 20/s) { continue; } level4Tmp = level4Tmp.concat(ll.next()); } l4 = level4Tmp; for(const ll of level4Tmp) { if(ll.center.y > level0.center.y) { ll.dir = 'top' level4[0].push(ll); } else if(ll.center.x < level0.center.x) { ll.dir = 'left' level4[1].push(ll); } else { ll.dir = 'right'; level4[2].push(ll); } } // let level5Tmp = [] // for(const ll of level4Tmp) { // if(ll.area < 1/s) { // continue; // } // level5Tmp = level5Tmp.concat(ll.next()); // } // for(const ll of level5Tmp) { // if(ll.center.y > level0.center.y) { // ll.dir = 'top' // level5[0].push(ll); // } else if(ll.center.x < level0.center.x) { // ll.dir = 'left' // level5[1].push(ll); // } else { // ll.dir = 'right'; // level5[2].push(ll); // } // } // for(const ll of l) { // ll.draw(); // } // for(const ll of l) { // for(const ll2 of ll.next()) { // for(const tra of ll2.next()) { // tra.draw(); // } // } // } // const [t2, t3, t4] = t.nextTriangles(); // t2.draw(); // t3.draw(); // t4.draw(); frameRate(10); } function mix(x, y, a) { return x(1-a)+y*a; } function clamp(value, min, max) { return Math.min(Math.max(value, min), max); } //w: start time //s: duration function scene(t, w, s) { return clamp(t - w, 0.0, s) / s; } function expEasingIn(t){ return Math.pow( 2., 13. * (t - 1.) ); } function expEasingOut(t) { return -Math.pow( 2., -10. * t) + 1.; } function circEasingInOut(t){ t /= .5; if (t < 1.) return -.5 * (Math.sqrt(1. - t*t) - 1.); t -= 2.; return .5 * (Math.sqrt(1. - t*t) + 1.); } function circEasingIn(t){ return - (Math.sqrt(1. - t*t) - 1.); } let frame = 0; function draw() { colorMode(RGB, 1, 1, 1) const t = Math.floor(frame/5) % 3;//0//frame * 0.2; //console.log(t); background(1); translate(-200 -width, height); const s = 2000; scale(s, -s*1.01); //strokeWeight(1/s); noStroke(); //const nv = level0.translated(new Vec2(width / s -(width / s) * expEasingIn(scene(t, 0, 1.5)), 0)); //fill(0, 1, 1); push(); translate(2, 0); for(const ll of level1) { ll.draw(t); } for(const ll of level2) { ll.draw(t); } for(const ll of l3) { ll.draw(t); } for(const ll of l4) { ll.draw(t); } rotate(PI/3); for(const ll of level1) { ll.draw(t); } for(const ll of level2) { ll.draw(t); } for(const ll of l3) { ll.draw(t); } for(const ll of l4) { ll.draw(t); } pop(); // rotate(PI / 2) translate(1, 0) push(); rotate(PI/3) rotate(-PI/3) level0.draw(); for(const ll of level1) { ll.draw(t); } for(const ll of level2) { ll.draw(t); } for(const ll of l3) { ll.draw(t); } for(const ll of l4) { ll.draw(t); } pop(); rotate(-PI/3) translate(-1, 0) level0.draw(); for(const ll of level1) { ll.draw(t); } for(const ll of level2) { ll.draw(t); } for(const ll of l3) { ll.draw(t); } for(const ll of l4) { ll.draw(t); } frame++; }