From 5f93512fac845306a1c797c807b6dcbd51816f6d Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Thu, 7 Sep 2023 10:32:44 +0200 Subject: [PATCH] functionality for adding multiple pendula --- public/data/scripts/ts/manager.ts | 75 +++++++++++++++++++----- public/data/scripts/ts/pendulum.ts | 10 ++-- public/data/styles/color_picker.css | 88 ----------------------------- public/data/styles/range_input.css | 7 ++- public/index.html | 24 +++++--- public/styles.css | 2 +- 6 files changed, 85 insertions(+), 121 deletions(-) delete mode 100644 public/data/styles/color_picker.css diff --git a/public/data/scripts/ts/manager.ts b/public/data/scripts/ts/manager.ts index 743739c..23ce585 100644 --- a/public/data/scripts/ts/manager.ts +++ b/public/data/scripts/ts/manager.ts @@ -2,12 +2,13 @@ class Manager { pendula: Pendulum[] = [] - timescale = 1; - gravity = 9.81; + timescale: number; + gravity: number; playing = false; - static Size = 200; + static SubSteps: number; + static Size = 20; init(){ // @ts-ignore @@ -15,8 +16,9 @@ class Manager { createApp({ data() { return { - gravity: manager.gravity, - timescale: manager.timescale, + gravity: 0, + timescale: 0, + subSteps: 0, playingBtn: "play" }; }, @@ -26,18 +28,29 @@ class Manager { }, timescale(newScale: number){ manager.timescale = newScale; + }, + subSteps(newSteps: number){ + Manager.SubSteps = newSteps; } }, methods: { togglePlay(){ manager.playing = !manager.playing; this.playingBtn = manager.playing ? "pause" : "play"; + }, + resetSimulationControls(){ + this.gravity = 9.81; + this.timescale = 1; + this.subSteps = 30; } }, + mounted() { + this.resetSimulationControls(); + }, name: "Simulation" }).mount("#simulation"); - createApp({ + let app = createApp({ data(){ return { segmentCount: 1, @@ -50,26 +63,52 @@ class Manager { multiple: false, pendulumCount: 10, changeProperty: "angle", - changeAmount: 0.05, + changeAmount: 0.0005, changeIndex: 0 } }, methods: { add() { if (this.multiple){ - + let changeAmount = this.changeAmount; + let changeIndex = this.changeIndex; + let color = p.color(this.color); + p.colorMode(p.HSB, 100); + for (let i = 0; i < this.pendulumCount; i++){ + let M = this.masses.slice(0, this.segmentCount); + let L = this.lengths.slice(0, this.segmentCount); + let startAngle = this.startAngle; + let progress = i / this.pendulumCount - 0.5; + switch (this.changeProperty){ + case "angle": + startAngle += progress * 360 * changeAmount; + break; + case "mass": + M[changeIndex] += progress * M[changeIndex] * changeAmount; + break; + case "length": + L[changeIndex] += progress * L[changeIndex] * changeAmount; + break; + } + if (this.rainbow){ + let hue = (progress + 0.5) * 100; + color = p.color(hue, 100, 100); + } + let newPendulum = new Pendulum(M, L, color, startAngle); + manager.pendula.push(newPendulum); + } + p.colorMode(p.RGB); } else { - let color = p.color(this.color) let M = this.masses.slice(0, this.segmentCount); let L = this.lengths.slice(0, this.segmentCount); + let color = p.color(this.color); let newPendulum = new Pendulum(M, L, color, this.startAngle); manager.pendula.push(newPendulum); } - p.colorMode(p.HSB, 100); - p.colorMode(p.RGB); + }, deleteAll(){ - if (confirm("Delete all pendulums?")){ + if (confirm("Delete all pendula?")){ manager.pendula.splice(0); } }, @@ -95,8 +134,16 @@ class Manager { this.resetMasses(); this.resetLengths(); }, - name: "Preparation" - }).mount("#preparation"); + name: "Add Pendula" + }); + app.config.globalProperties.$filters = { + round(value: number, n: number){ + if (!value) + return "0"; + return +value.toFixed(n); + } + } + app.mount("#preparation"); } diff --git a/public/data/scripts/ts/pendulum.ts b/public/data/scripts/ts/pendulum.ts index 9901c97..0b838be 100644 --- a/public/data/scripts/ts/pendulum.ts +++ b/public/data/scripts/ts/pendulum.ts @@ -22,11 +22,9 @@ class Pendulum { // using position based dynamics update(h: number) { - const subSteps = 50; + h /= Manager.SubSteps; - h /= subSteps; - - for (let k = 0; k < subSteps; k++) { + for (let k = 0; k < Manager.SubSteps; k++) { // Classic PBD needs multiple loops // Here, I can put all operations safely into one single loop, @@ -38,7 +36,7 @@ class Pendulum { for (let i = 0; i < this.size; i++) { // apply external force (gravity) - this.V[i].addC(0, manager.gravity * h * 50); + this.V[i].addC(0, manager.gravity * h); // euler step let currentP = Vector.Add(this.X[i],Vector.Mult(this.V[i], h)); @@ -79,7 +77,7 @@ class Pendulum { p.strokeWeight(1); p.fill(255); - let scale = p.height / Manager.Size; + let scale = p.height * 0.95 / Manager.Size; let p1 = new Vector(0, 0); for (let p2 of this.X){ p2 = p2.copy(); diff --git a/public/data/styles/color_picker.css b/public/data/styles/color_picker.css deleted file mode 100644 index a5b510e..0000000 --- a/public/data/styles/color_picker.css +++ /dev/null @@ -1,88 +0,0 @@ -#color_picker{ - width: 300px; - height: 25%; - margin: 20px; - margin-top: 50px; - border: 5px solid #000; - background-color: #000; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - position: relative; -} -#color_picker_numeric{ - width: 80%; - padding: 5%; - margin: 5%; - background-color: #888; - border-radius: 10px; - overflow: hidden; -} -.color_picker_rgb{ - float: left; - width: 22%; - height: 35px; - font-size: 25px; - color: #000; -} -.color_picker_rgb:nth-child(1){ - margin-right: 10%; - margin-left: 3%; - background-color: #F00; - -} -.color_picker_rgb:nth-child(2){ - background-color: #0F0; -} -.color_picker_rgb:nth-child(3){ - margin-left: 10%; - background-color: #00F; - color: #FFF; -} -#color_picker_hex{ - width: 50%; - height: 30px; - font-size: 25px; - margin: 10% 25% 0 25%; -} -#saturation{ - position: relative; - width: calc(100% - 33px); - height: 100%; - background: linear-gradient(to right, #FFF 0%, #F00 100%); - float: left; - margin-right: 6px; -} -#value { - width: 100%; - height: 100%; - background: linear-gradient(to top, #000 0%, rgba(255,255,255,0) 100%); -} -#sb_picker{ - border: 2px solid; - border-color: #FFF; - position: absolute; - width: 14px; - height: 14px; - border-radius: 10px; - bottom: 50px; - left: 50px; - box-sizing: border-box; - z-index: 10; -} -#hue { - width: 27px; - height: 100%; - position: relative; - float: left; - background: linear-gradient(to bottom, #F00 0%, #F0F 17%, #00F 34%, #0FF 50%, #0F0 67%, #FF0 84%, #F00 100%); -} -#hue_picker { - position: absolute; - background: #000; - border-bottom: 1px solid #000; - top: 0; - width: 27px; - height: 2px; -} \ No newline at end of file diff --git a/public/data/styles/range_input.css b/public/data/styles/range_input.css index ada1a11..16920ad 100644 --- a/public/data/styles/range_input.css +++ b/public/data/styles/range_input.css @@ -2,6 +2,7 @@ input[type=range] { -webkit-appearance: none; margin: 10px 0; width: 100%; + height: 20px; background: none; } input[type=range]:focus { @@ -9,7 +10,7 @@ input[type=range]:focus { } input[type=range]::-webkit-slider-runnable-track { width: 100%; - height: 8.4px; + height: 9px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; @@ -33,7 +34,7 @@ input[type=range]:focus::-webkit-slider-runnable-track { } input[type=range]::-moz-range-track { width: 100%; - height: 8.4px; + height: 9px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; @@ -52,7 +53,7 @@ input[type=range]::-moz-range-thumb { } input[type=range]::-ms-track { width: 100%; - height: 8.4px; + height: 9px; cursor: pointer; animate: 0.2s; background: transparent; diff --git a/public/index.html b/public/index.html index 3734d94..36e5ee0 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,6 @@ - Pendulum @@ -27,14 +26,14 @@ ({{ i - 1 }}) {{ masses[i - 1] }}kg - {{ lengths[i - 1] }}m + {{ $filters.round(lengths[i - 1], 1) }}m
- + - +
- - + +
@@ -94,7 +93,14 @@ Timescale: x{{ timescale }} - + +
+ + +
diff --git a/public/styles.css b/public/styles.css index 0080834..fd48d01 100644 --- a/public/styles.css +++ b/public/styles.css @@ -150,7 +150,7 @@ button:active { border-color: #9a9a9a; } -.reset_segments_btn { +.reset_btn { background-image: url("data/images/refresh.svg"); background-color: #cbcbcb; border-color: #9a9a9a;