diff --git a/public/data/images/add.svg b/public/data/images/add.svg new file mode 100644 index 0000000..c907b9a --- /dev/null +++ b/public/data/images/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/data/images/delete.svg b/public/data/images/delete.svg new file mode 100644 index 0000000..d985243 --- /dev/null +++ b/public/data/images/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/data/scripts/ts/manager.ts b/public/data/scripts/ts/manager.ts index 012b94a..a2241ff 100644 --- a/public/data/scripts/ts/manager.ts +++ b/public/data/scripts/ts/manager.ts @@ -15,7 +15,7 @@ class Manager { let hue = i / count * 100; let color = p.color(hue, 100, 100); this.pendulums.push( - new Pendulum([1, 1, 1, 1, 1, 1, 1, 1], [50, 50, 50, 50, 50, 50, 50, 100 + i / count / 1000000], color) + new Pendulum([1, 1, 1, 1, 1, 1, 1, 1], [50, 50, 50, 50, 50, 50, 50, 100 + i / count / 10000], color) ); } p.colorMode(p.RGB); @@ -34,11 +34,11 @@ class Manager { }; }, watch: { - gravity(newGravity: string) { - manager.gravity = parseFloat(newGravity); + gravity(newGravity: number) { + manager.gravity = newGravity; }, - timescale(newScale: string){ - manager.timescale = parseFloat(newScale); + timescale(newScale: number){ + manager.timescale = newScale; } }, methods: { @@ -46,13 +46,45 @@ class Manager { manager.playing = !manager.playing; this.playingBtn = manager.playing ? "pause" : "play"; } - } + }, + name: "Simulation" }).mount("#simulation"); + + createApp({ + data(){ + return { + segmentCount: 1, + masses: [], + lengths: [], + startAngle: 90, + color: "#ffffff", + rainbow: false, + multiple: false, + pendulumCount: 10, + changeProperty: "angle", + changeAmount: 0.05, + changeIndex: 0 + } + }, + methods: { + add() { + + }, + }, + mounted() { + for (let i = 0; i < 20; i++){ + this.masses.push(1); + this.lengths.push(1); + } + }, + name: "Preparation" + }).mount("#preparation"); + } update(){ if (this.playing) { - const h = this.timescale / (p.frameRate() || 60); + const h = this.timescale / Math.max(p.frameRate(), 1); this.pendulums.forEach(p => p.update(h)); } } diff --git a/public/data/scripts/ts/pendulum.ts b/public/data/scripts/ts/pendulum.ts index 5aeddbd..dd46338 100644 --- a/public/data/scripts/ts/pendulum.ts +++ b/public/data/scripts/ts/pendulum.ts @@ -27,9 +27,15 @@ class Pendulum { for (let k = 0; k < subSteps; k++) { - let previousP = new Vector(0, 0); + // Classic PBD needs multiple loops + // Here, I can put all operations safely into one single loop, + // because the positions and velocities in X, V are sorted + // from the pendulum's origin to it's end which means + // that only direct neighbours affect each other + let previousP = new Vector(0, 0); for (let i = 0; i < this.size; i++) { + // apply external force (gravity) this.V[i].addC(0, manager.gravity * h * 50); @@ -69,7 +75,7 @@ class Pendulum { p.push(); p.stroke(this.color); - p.strokeWeight(2); + p.strokeWeight(1); p.fill(255); let p1 = new Vector(0, 0); diff --git a/public/data/styles/range_input.css b/public/data/styles/range_input.css index 6c9eaeb..ada1a11 100644 --- a/public/data/styles/range_input.css +++ b/public/data/styles/range_input.css @@ -1,6 +1,6 @@ input[type=range] { -webkit-appearance: none; - margin: 18px 0; + margin: 10px 0; width: 100%; background: none; } diff --git a/public/index.html b/public/index.html index d981ef9..8b46170 100644 --- a/public/index.html +++ b/public/index.html @@ -2,9 +2,9 @@ - - - + + + @@ -17,17 +17,81 @@
Preparation - + +
+ MassLength + +
+ + +
+ +
+ +
Simulation
diff --git a/public/styles.css b/public/styles.css index 1774aa5..b66c1e2 100644 --- a/public/styles.css +++ b/public/styles.css @@ -31,7 +31,7 @@ button:hover{cursor: pointer;} } body { - overflow: auto; + overflow: hidden; } /** @@ -64,6 +64,9 @@ body { padding: var(--opt-padding); border-right: var(--opt-border) solid rgb(150, 150, 150); background-color: rgb(40, 40, 40); + + display: flex; + flex-direction: column; } #options *:not(input[type=number], input[type=button]){ color: white; @@ -71,29 +74,67 @@ body { fieldset { border-radius: 5px; + margin: 10px; } +fieldset > legend { + font-size: 25px; +} input { margin: 5px; } -input[type=button]{ - border: 3px solid #0060df; - border-radius: 5px; - line-height: 30px; - font-size: 30px; +#preparation { + overflow-y: auto; } -#play_btn { +#segment_view { + display: grid; + grid-template-columns: 10% 15% 30% 15% 30%; +} + +#segment_header_mass { + grid-column: 2 / span 2; +} + +#segment_header_length { + grid-column: 4 / span 2; +} + +.segment_label { + display: inline-flex; + align-items: center; + justify-content: center; +} + +button { + margin-top: 10px; width: 100%; - border: 4px solid cornflowerblue; - border-radius: 5px; height: 50px; + border: 3px solid black; + border-radius: 5px; background-size: contain; background-position: center; background-repeat: no-repeat; } +button:hover{ + filter: brightness(80%); +} +button:active { + filter: brightness(60%); +} + +#add_btn{ + border-color: #007a00; + background-color: #d3ffd3; + background-image: url("data/images/add.svg"); +} + +#play_btn { + border-color: #0000c2; + background-color: #b1b1ff; +} #play_btn.play { background-image: url("data/images/play.svg");