From 1e14a22c9f1b749a2f92c9d05436294ad9341632 Mon Sep 17 00:00:00 2001 From: Casey_Nelson <91818705+CaseyNelson314@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:40:22 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=E3=81=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/field3d.ts | 202 ++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 107 deletions(-) diff --git a/app/script/field3d.ts b/app/script/field3d.ts index 017784a..c74aa84 100644 --- a/app/script/field3d.ts +++ b/app/script/field3d.ts @@ -2,97 +2,6 @@ import * as THREE from 'three'; import { Charge, ChargeType } from './charge'; import { MeshLineGeometry, MeshLineMaterial } from '@lume/three-meshline' - -/** - * 任意の座標における全電荷からの電界ベクトルを計算 - * @param charges 電荷の配列 - * @param position 任意の座標 - * @returns - */ -const ElectricFieldVector = ( - charges: Charge[], - position: THREE.Vector3 -) => { - const electricFieldVector = new THREE.Vector3(); - - for (const charge of charges) { - electricFieldVector.add(charge.electricFieldVector(position)); - } - - return electricFieldVector; -} - - -/** - * 電気力線の連続点を生成 - * @param originCharge 線電荷が出る電荷 - * @param charges 電荷の配列 - * @param beginPoint 始点 - * @param dirVector 方向ベクトル - * @param simDistance シミュレーション距離 (原点からの距離) - * @returns - */ -const ElectricForceLinePoints = ( - originCharge: Charge, - charges: Charge[], - beginPoint: THREE.Vector3, - dirVector: THREE.Vector3, - simDistance: number -) => { - - const points = [beginPoint.clone()]; - const origin = beginPoint.clone().add(dirVector); - - for (let i = 0; i < 2000; ++i) { - - // 任意の座標における電界ベクトルを計算 - const electricFieldVector = ElectricFieldVector(charges, origin); - - // 負電荷の場合も正電荷と同様の力線を描画するため、電界ベクトルを反転させる - if (originCharge.getChargeType() === ChargeType.Minus) { - electricFieldVector.multiplyScalar(-1); - } - - // 電界ベクトルの方向に長さ1だけ移動 (これを繰り返すことで電気力線を生成) - origin.add(electricFieldVector.normalize()); - points.push(origin.clone()); - - // 力線が他の電荷と接触したら終了 - for (const charge of charges) { - - // 自分自身との衝突判定は行わない - if (charge === originCharge) { - continue; - } - - // 電荷同士の正負が同じなら衝突判定を行わない - if (charge.getChargeType() === originCharge.getChargeType()) { - continue; - } - - // 中性電荷との衝突判定は行わない - if (charge.getChargeType() === ChargeType.Neutral) { - continue; - } - - // 他電荷との衝突判定 - if (charge.isContact(origin, 1.5)) { - return points; - } - - } - - // 原点からの距離がシミュレーション距離を超えたら終了 - if (origin.lengthSq() > simDistance ** 2) { - break; - } - } - - return points; - -}; - - /** * 電気力線 */ @@ -108,7 +17,6 @@ class ElectricLines3D extends THREE.Object3D { this.charges = charges; this.lineMaterial = new MeshLineMaterial({ color: 0xffffff, lineWidth: 1 }); - this.coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); this.coneMaterial = new THREE.MeshBasicMaterial({ color: 0xbbbbbb }); @@ -178,32 +86,112 @@ class ElectricLines3D extends THREE.Object3D { export class Field3D extends THREE.Object3D { private charges: Charge[]; - private electric_lines_3d: ElectricLines3D | null; + private electricLines3d: THREE.Object3D; constructor(charges: Charge[]) { super(); this.charges = charges; - this.electric_lines_3d = null; + this.electricLines3d = new ElectricLines3D(charges); } + + + /** + * 任意の座標における全電荷からの電界ベクトルを計算 + * @param charges 電荷の配列 + * @param position 任意の座標 + * @returns + */ + electricFieldVector = (position: THREE.Vector3) => { + const electricFieldVector = new THREE.Vector3(); + + for (const charge of this.charges) { + electricFieldVector.add(charge.electricFieldVector(position)); + } + + return electricFieldVector; + } + + + /** + * 電気力線の連続点を生成 + * @param originCharge 線電荷が出る電荷 + * @param charges 電荷の配列 + * @param beginPoint 始点 + * @param dirVector 方向ベクトル + * @param simDistance シミュレーション距離 (原点からの距離) + * @returns + */ + electricForceLinePoints = ( + originCharge: Charge, + beginPoint: THREE.Vector3, + dirVector: THREE.Vector3, + simDistance: number + ) => { + + const points = [beginPoint.clone()]; + const origin = beginPoint.clone().add(dirVector); + + for (let i = 0; i < 2000; ++i) { + + // 任意の座標における電界ベクトルを計算 + const electricFieldVector = this.electricFieldVector(origin); + + // 負電荷の場合も正電荷と同様の力線を描画するため、電界ベクトルを反転させる + if (originCharge.getChargeType() === ChargeType.Minus) { + electricFieldVector.multiplyScalar(-1); + } + + // 電界ベクトルの方向に長さ1だけ移動 (これを繰り返すことで電気力線を生成) + origin.add(electricFieldVector.normalize()); + points.push(origin.clone()); + + // 力線が他の電荷と接触したら終了 + for (const charge of this.charges) { + + // 自分自身との衝突判定は行わない + if (charge === originCharge) { + continue; + } + + // 電荷同士の正負が同じなら衝突判定を行わない + if (charge.getChargeType() === originCharge.getChargeType()) { + continue; + } + + // 中性電荷との衝突判定は行わない + if (charge.getChargeType() === ChargeType.Neutral) { + continue; + } + + // 他電荷との衝突判定 + if (charge.isContact(origin, 1.5)) { + return points; + } + + } + + // 原点からの距離がシミュレーション距離を超えたら終了 + if (origin.lengthSq() > simDistance ** 2) { + break; + } + } + + return points; + + }; + + + /// フィールドの更新 update = () => { - if (this.children.find((child) => child === this.electric_lines_3d) != null) - this.electric_lines_3d?.update(); + if (this.children.find((child) => child === this.electricLines3d) != null) + this.electricLines3d?.update(); } /// 電気力線の表示切替 - enableElectricLines = (enable: boolean) => { - if (enable) { - if (this.electric_lines_3d == null) - this.electric_lines_3d = new ElectricLines3D(this.charges); - else - this.electric_lines_3d.update(); - this.add(this.electric_lines_3d); - } - else { - this.remove(this.electric_lines_3d as ElectricLines3D); - } + enableElectricLines = (visible: boolean) => { + this.electricLines3d.visible = visible; }; } From 50f6676f7095c5025de9336b127a4f2c60e40f7c Mon Sep 17 00:00:00 2001 From: CaseyNelson Date: Fri, 26 Jan 2024 23:07:06 +0900 Subject: [PATCH 2/8] s --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c663ca1..a9bbcbb 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,14 @@ d# EFSim [![GitHub Pages Deploy](https://github.com/CaseyNelson314/EFSim/actions 空間内で電荷を選択することで、パラメータ編集モードに切り替わり、電荷の位置、回転角、電荷量、電荷密度などのパラメーターを編集できます。(編集できるパラメータは電荷の種類によって異なります) -## 電界ベクトル +## 電界強度 電界ベクトル - 点電荷 $$ E(r) = \frac{Q}{4 \pi \varepsilon_0 r^{2}} \qquad -\boldsymbol{E}(\boldsymbol{r}) = \frac{Q}{4 \pi \varepsilon_0 \lvert\boldsymbol{r}\rvert^{3}} \boldsymbol{r} +\vec{E}(\vec{r}) = \frac{Q}{4 \pi \varepsilon_0 \lvert\vec{r}\rvert^{3}} \vec{r} $$ - 無限長線電荷 @@ -29,7 +29,7 @@ $$ $$ E(r) = \frac{\lambda}{2 \pi \varepsilon_0 r} \qquad -\boldsymbol{E}(\boldsymbol{r}) = \frac{\lambda}{2 \pi \varepsilon_0\lvert\boldsymbol{r}\rvert^{2}} \boldsymbol{r} +\vec{E}(\vec{r}) = \frac{\lambda}{2 \pi \varepsilon_0\lvert\vec{r}\rvert^{2}} \vec{r} $$ - 無限面電荷 @@ -37,7 +37,7 @@ $$ $$ E(r) = \frac{\sigma}{2 \varepsilon_0} \qquad -\boldsymbol{E}(\boldsymbol{r}) = \frac{\sigma}{2 \varepsilon_0 \lvert\boldsymbol{r}\rvert} \boldsymbol{r} +\vec{E}(\vec{r}) = \frac{\sigma}{2 \varepsilon_0 \lvert\vec{r}\rvert} \vec{r} $$ - 球表面電荷 @@ -49,8 +49,8 @@ $$ \end{cases} \qquad \begin{cases} - \boldsymbol{E}(\boldsymbol{r}) = \frac{\sigma a^{2}}{\varepsilon_0 \lvert\boldsymbol{r}\rvert^{3}} \boldsymbol{r} & (a \leq \lvert\boldsymbol{r}\rvert) \\ - \boldsymbol{E}(\boldsymbol{r}) = \boldsymbol{0} & (0 \leq \lvert\boldsymbol{r}\rvert < a) + \vec{E}(\vec{r}) = \frac{\sigma a^{2}}{\varepsilon_0 \lvert\vec{r}\rvert^{3}} \vec{r} & (a \leq \lvert\vec{r}\rvert) \\ + \vec{E}(\vec{r}) = \vec{0} & (0 \leq \lvert\vec{r}\rvert < a) \end{cases} $$ @@ -63,8 +63,8 @@ $$ \end{cases} \qquad \begin{cases} - \boldsymbol{E}(\boldsymbol{r}) = \frac{\rho a^{3}}{3 \varepsilon_0 \lvert\boldsymbol{r}\rvert^{3}} \boldsymbol{r} & (a \leq \lvert\boldsymbol{r}\rvert) \\ - \boldsymbol{E}(\boldsymbol{r}) = \frac{\rho}{3 \varepsilon_0} \boldsymbol{r} & (0 \leq \lvert\boldsymbol{r}\rvert < a) + \vec{E}(\vec{r}) = \frac{\rho a^{3}}{3 \varepsilon_0 \lvert\vec{r}\rvert^{3}} \vec{r} & (a \leq \lvert\vec{r}\rvert) \\ + \vec{E}(\vec{r}) = \frac{\rho}{3 \varepsilon_0} \vec{r} & (0 \leq \lvert\vec{r}\rvert < a) \end{cases} $$ @@ -77,8 +77,8 @@ $$ \end{cases} \qquad \begin{cases} - \boldsymbol{E}(\boldsymbol{r}) = \frac{ \sigma a}{\varepsilon_0 \lvert\boldsymbol{r}\rvert^{2}} \boldsymbol{r} & (a \leq \lvert\boldsymbol{r}\rvert) \\ - \boldsymbol{E}(\boldsymbol{r}) = \boldsymbol{0} & (0 \leq \lvert\boldsymbol{r}\rvert < a) + \vec{E}(\vec{r}) = \frac{ \sigma a}{\varepsilon_0 \lvert\vec{r}\rvert^{2}} \vec{r} & (a \leq \lvert\vec{r}\rvert) \\ + \vec{E}(\vec{r}) = \vec{0} & (0 \leq \lvert\vec{r}\rvert < a) \end{cases} $$ @@ -91,8 +91,8 @@ $$ \end{cases} \qquad \begin{cases} - \boldsymbol{E}(\boldsymbol{r}) = \frac{\rho a^{2}}{2 \varepsilon_0 \lvert\boldsymbol{r}\rvert^{2}} \boldsymbol{r} & (a \leq \lvert\boldsymbol{r}\rvert) \\ - \boldsymbol{E}(\boldsymbol{r}) = \frac{\rho}{2 \varepsilon_0} \boldsymbol{r} & (0 \leq \lvert\boldsymbol{r}\rvert < a) + \vec{E}(\vec{r}) = \frac{\rho a^{2}}{2 \varepsilon_0 \lvert\vec{r}\rvert^{2}} \vec{r} & (a \leq \lvert\vec{r}\rvert) \\ + \vec{E}(\vec{r}) = \frac{\rho}{2 \varepsilon_0} \vec{r} & (0 \leq \lvert\vec{r}\rvert < a) \end{cases} $$ @@ -101,14 +101,14 @@ $$ | 値 | 意味 | 単位 | | :------------------------------: | :------------------: | :--------------: | | $E(r)$ | 電界強度 | $\mathrm{V/m}$ | - | $\boldsymbol{E}(\boldsymbol{r})$ | 電界ベクトル | $(\mathrm{V/m})$ | + | $\vec{E}(\vec{r})$ | 電界ベクトル | $(\mathrm{V/m})$ | | $\varepsilon_0$ | 真空中の誘電率 | $\mathrm{F/m}$ | | $q$ | 電荷量 | $\mathrm{C}$ | | $\lambda$ | 線電荷密度 | $\mathrm{C/m}$ | | $\sigma$ | 面電荷密度 | $\mathrm{C/m^2}$ | | $\rho$ | 体積電荷密度 | $\mathrm{C/m^3}$ | | $r$ | 電荷との距離 | $\mathrm{m}$ | - | $\boldsymbol{r}$ | 電荷との距離ベクトル | $(\mathrm{m})$ | + | $\vec{r}$ | 電荷との距離ベクトル | $(\mathrm{m})$ | | $a$ | 半径 | $\mathrm{m}$ | ## 開発者用 From b6f020baca140716dbded2296e16e04a23665192 Mon Sep 17 00:00:00 2001 From: CaseyNelson Date: Fri, 26 Jan 2024 23:45:54 +0900 Subject: [PATCH 3/8] update readme --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a9bbcbb..6d4b6ac 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ d# EFSim [![GitHub Pages Deploy](https://github.com/CaseyNelson314/EFSim/actions 空間内で電荷を選択することで、パラメータ編集モードに切り替わり、電荷の位置、回転角、電荷量、電荷密度などのパラメーターを編集できます。(編集できるパラメータは電荷の種類によって異なります) -## 電界強度 電界ベクトル +## 電界強度式 電界ベクトル式 - 点電荷 @@ -98,18 +98,18 @@ $$ - 式中の記号詳細 - | 値 | 意味 | 単位 | - | :------------------------------: | :------------------: | :--------------: | - | $E(r)$ | 電界強度 | $\mathrm{V/m}$ | - | $\vec{E}(\vec{r})$ | 電界ベクトル | $(\mathrm{V/m})$ | - | $\varepsilon_0$ | 真空中の誘電率 | $\mathrm{F/m}$ | - | $q$ | 電荷量 | $\mathrm{C}$ | - | $\lambda$ | 線電荷密度 | $\mathrm{C/m}$ | - | $\sigma$ | 面電荷密度 | $\mathrm{C/m^2}$ | - | $\rho$ | 体積電荷密度 | $\mathrm{C/m^3}$ | - | $r$ | 電荷との距離 | $\mathrm{m}$ | - | $\vec{r}$ | 電荷との距離ベクトル | $(\mathrm{m})$ | - | $a$ | 半径 | $\mathrm{m}$ | + | 値 | 意味 | 単位 | + | :-------------: | :------------------: | :--------------: | + | $E$ | 電界強度 | $\mathrm{V/m}$ | + | $\vec{E}$ | 電界ベクトル | $(\mathrm{V/m})$ | + | $r$ | 電荷との距離 | $\mathrm{m}$ | + | $\vec{r}$ | 電荷との距離ベクトル | $(\mathrm{m})$ | + | $\varepsilon_0$ | 真空中の誘電率 | $\mathrm{F/m}$ | + | $q$ | 電荷量 | $\mathrm{C}$ | + | $\lambda$ | 線電荷密度 | $\mathrm{C/m}$ | + | $\sigma$ | 面電荷密度 | $\mathrm{C/m^2}$ | + | $\rho$ | 体積電荷密度 | $\mathrm{C/m^3}$ | + | $a$ | 半径 | $\mathrm{m}$ | ## 開発者用 @@ -157,13 +157,13 @@ app/ 1. 電気力線の出る適当な方向を決め、その方向に力線を長さ 1 だけ進める。 -2. 進めた先の座標における電界ベクトルを求め、その方向に長さ 1 の力線を長さ 1 だけ進める。 +2. 進めた先の座標における電界ベクトルを求め、その方向に力線を長さ 1 だけ進める。 3. 2.を他の電荷に当たる、長さ制限になるまで繰り返し 1 本の電気力線を生成。 -4. 1.で決めた方向を調整することで複数の電気力線を生成。 +4. 1.で決める方向を調整することで複数の電気力線を生成。 - + ### クラス相関 From 28b2d3eab5a62525a212681a9498709f5105b39e Mon Sep 17 00:00:00 2001 From: CaseyNelson Date: Sat, 27 Jan 2024 15:06:42 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=E9=9B=BB=E8=8D=B7=E9=85=8D=E5=88=97?= =?UTF-8?q?=E3=82=92=E7=AE=A1=E7=90=86=E3=81=99=E3=82=8B=E3=82=AF=E3=83=A9?= =?UTF-8?q?=E3=82=B9=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/field3d.ts | 86 ++++++++++++++++++++++++++++++++----------- app/script/main.ts | 4 +- app/script/store.ts | 30 +++++++++++++-- 3 files changed, 94 insertions(+), 26 deletions(-) diff --git a/app/script/field3d.ts b/app/script/field3d.ts index c74aa84..d960d4c 100644 --- a/app/script/field3d.ts +++ b/app/script/field3d.ts @@ -7,14 +7,15 @@ import { MeshLineGeometry, MeshLineMaterial } from '@lume/three-meshline' */ class ElectricLines3D extends THREE.Object3D { - private charges: Charge[]; + private field: ElectricField; private lineMaterial: MeshLineMaterial; private coneGeometry: THREE.ConeGeometry; private coneMaterial: THREE.MeshBasicMaterial; - constructor(charges: Charge[]) { + constructor(field: ElectricField) { super(); - this.charges = charges; + + this.field = field; this.lineMaterial = new MeshLineMaterial({ color: 0xffffff, lineWidth: 1 }); this.coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); @@ -24,7 +25,7 @@ class ElectricLines3D extends THREE.Object3D { } createELines() { - for (const charge of this.charges) { + for (const charge of this.field.charges) { if (charge.getChargeType() === ChargeType.Neutral) continue; @@ -33,7 +34,8 @@ class ElectricLines3D extends THREE.Object3D { for (const point of points) { // 電気力線の連続点から線分ジオメトリを生成 - const points = ElectricForceLinePoints(charge, this.charges, point.begin, point.direction, 500); + const points = this.field.electricForceLinePoints(charge, point.begin, point.direction, 500); + if (points.length < 2) { // 2点以上ないと線分を生成できない continue; @@ -82,28 +84,36 @@ class ElectricLines3D extends THREE.Object3D { } } -/// 電界 -export class Field3D extends THREE.Object3D { - private charges: Charge[]; - private electricLines3d: THREE.Object3D; - constructor(charges: Charge[]) { - super(); +/** + * 電界 + */ +class ElectricField { + + /** + * 電荷の配列 + */ + charges: Charge[]; + + + /** + * コンストラクタ + * @param charges 電荷の配列 + */ + constructor(charges: Charge[]) { this.charges = charges; - this.electricLines3d = new ElectricLines3D(charges); } - /** * 任意の座標における全電荷からの電界ベクトルを計算 - * @param charges 電荷の配列 * @param position 任意の座標 * @returns */ electricFieldVector = (position: THREE.Vector3) => { + const electricFieldVector = new THREE.Vector3(); for (const charge of this.charges) { @@ -111,17 +121,17 @@ export class Field3D extends THREE.Object3D { } return electricFieldVector; + } /** - * 電気力線の連続点を生成 + * 特定の電荷からでる電気力線の連続点を生成 * @param originCharge 線電荷が出る電荷 - * @param charges 電荷の配列 - * @param beginPoint 始点 - * @param dirVector 方向ベクトル + * @param beginPoint 始点座標 + * @param dirVector 方向ベクトル (単位ベクトル) * @param simDistance シミュレーション距離 (原点からの距離) - * @returns + * @returns 電気力線の連続点 */ electricForceLinePoints = ( originCharge: Charge, @@ -130,12 +140,15 @@ export class Field3D extends THREE.Object3D { simDistance: number ) => { + // 電気力線の連続点 const points = [beginPoint.clone()]; + + // 始点から方向ベクトルの方向に1だけ移動した座標を新たな始点とする const origin = beginPoint.clone().add(dirVector); + // 始点を電界ベクトルを基に移動させる for (let i = 0; i < 2000; ++i) { - // 任意の座標における電界ベクトルを計算 const electricFieldVector = this.electricFieldVector(origin); // 負電荷の場合も正電荷と同様の力線を描画するため、電界ベクトルを反転させる @@ -184,14 +197,43 @@ export class Field3D extends THREE.Object3D { - /// フィールドの更新 +} + +/// 電界 +export class Field3D extends THREE.Object3D { + + + private field: ElectricField; + private electricLines3d: THREE.Object3D; + + + /** + * コンストラクタ + * @param charges 電荷の配列 + */ + constructor(charges: Charge[]) { + super(); + this.field = new ElectricField(charges); + this.electricLines3d = new ElectricLines3D(this.field); + } + + + /** + * フィールドの更新 + */ update = () => { if (this.children.find((child) => child === this.electricLines3d) != null) this.electricLines3d?.update(); } - /// 電気力線の表示切替 + + /** + * 電気力線の表示/非表示を切り替える + * @param visible 表示するかどうか + */ enableElectricLines = (visible: boolean) => { this.electricLines3d.visible = visible; }; + + } diff --git a/app/script/main.ts b/app/script/main.ts index cdf3755..5697e2e 100644 --- a/app/script/main.ts +++ b/app/script/main.ts @@ -1,6 +1,5 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; -import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; import { Editor } from './editor'; import { Dragger } from './dragger'; import { Field3D } from './field3d'; @@ -76,6 +75,7 @@ const start = () => { Store.RegisterChargeGenerator("InfinityCylinderSurfaceCharge", InfinityCylinderSurfaceCharge.fromJSON); } + // 点電荷たち const charges: Charge[] = []; @@ -231,6 +231,7 @@ const start = () => { }); } + // 電気力線 表示/非表示 { const checkbox = document.getElementById('checkbox_electric_lines') as HTMLInputElement; @@ -240,6 +241,7 @@ const start = () => { }); } + const main = () => { requestAnimationFrame(main); diff --git a/app/script/store.ts b/app/script/store.ts index 3ca652c..35b1c6c 100644 --- a/app/script/store.ts +++ b/app/script/store.ts @@ -3,20 +3,38 @@ import { Charge } from "./charge"; export namespace Store { - const generator: { [key: string]: (json: any) => Charge } = {}; + const chargeGenerator: { [key: string]: (json: any) => Charge } = {}; export const RegisterChargeGenerator = (name: string, gen: (json: any) => T) => { - generator[name] = gen; + chargeGenerator[name] = gen; } + /** + * JSONを電荷の配列に変換する + * @param chargesJson JSON + * @note JSON format: + * ```json + * [ + * { + * "name": "ChargeName", + * // ...ChargeName.toJSON() で得られるJSON + * }, + * { + * "name": "ChargeName", + * // ...ChargeName.toJSON() で得られるJSON + * }, + * ] + * ``` + * @returns 電荷の配列 + */ export const JsonToCharges = (chargesJson: any) => { const charges: Charge[] = []; for (const chargeJson of chargesJson) { - const gen = generator[chargeJson.name]; + const gen = chargeGenerator[chargeJson.name]; if (gen === undefined) { console.error(`generator for ${chargeJson.name} is not registered.`); continue; @@ -31,6 +49,12 @@ export namespace Store { return charges; } + + /** + * 電荷の配列をJSONに変換する + * @param charges 電荷の配列 + * @returns JSON + */ export const ChargesToJson = (charges: Charge[]) => { const json: any = []; From 707daee26e4fa8849a18adc1393f3faacac560e1 Mon Sep 17 00:00:00 2001 From: Casey_Nelson <91818705+CaseyNelson314@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:36:16 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=E3=82=B8=E3=82=AA=E3=83=A1=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=82=92=E3=83=9E=E3=83=BC=E3=82=B8=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=81=93=E3=81=A8=E3=81=A7=E3=83=91=E3=83=95=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=9E=E3=83=B3=E3=82=B9=E5=90=91=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/field3d.ts | 87 +++++++++++++++---------------------------- app/script/main.ts | 29 ++++++++------- 2 files changed, 44 insertions(+), 72 deletions(-) diff --git a/app/script/field3d.ts b/app/script/field3d.ts index d960d4c..33025bb 100644 --- a/app/script/field3d.ts +++ b/app/script/field3d.ts @@ -1,30 +1,28 @@ import * as THREE from 'three'; import { Charge, ChargeType } from './charge'; import { MeshLineGeometry, MeshLineMaterial } from '@lume/three-meshline' +import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils'; /** * 電気力線 */ -class ElectricLines3D extends THREE.Object3D { +export class ElectricLines3D extends THREE.Object3D { private field: ElectricField; - private lineMaterial: MeshLineMaterial; - private coneGeometry: THREE.ConeGeometry; - private coneMaterial: THREE.MeshBasicMaterial; + private lineMaterial = new MeshLineMaterial({ color: new THREE.Color(0xffffff), lineWidth: 1 }) + private coneMaterial = new THREE.MeshBasicMaterial({ color: 0xbbbbbb }); + private coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); constructor(field: ElectricField) { super(); - this.field = field; - - this.lineMaterial = new MeshLineMaterial({ color: 0xffffff, lineWidth: 1 }); - this.coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); - this.coneMaterial = new THREE.MeshBasicMaterial({ color: 0xbbbbbb }); - this.createELines(); } createELines() { + + const lines: MeshLineGeometry[] = []; + for (const charge of this.field.charges) { if (charge.getChargeType() === ChargeType.Neutral) continue; @@ -36,20 +34,21 @@ class ElectricLines3D extends THREE.Object3D { // 電気力線の連続点から線分ジオメトリを生成 const points = this.field.electricForceLinePoints(charge, point.begin, point.direction, 500); + // 力線を生成 if (points.length < 2) { // 2点以上ないと線分を生成できない continue; } - const geometry = new MeshLineGeometry(); - geometry.setPoints(points); - const line = new THREE.Mesh(geometry, this.lineMaterial); - this.add(line); + const lineGeometry = new MeshLineGeometry(); + lineGeometry.setPoints(points); + lines.push(lineGeometry); + + // 矢印を生成 if (points.length < 20) { // 3点以上ないと矢印を生成できない continue; } - // 電気力線上に一定間隔で矢印を生成 const step = points.length / 3; for (let i = step; i + 1 < points.length; i += step) { @@ -57,22 +56,29 @@ class ElectricLines3D extends THREE.Object3D { const diff = new THREE.Vector3(); diff.subVectors(points[Math.floor(i + 1)]!, origin); - const cone = new THREE.Mesh(this.coneGeometry, this.coneMaterial); - cone.position.copy(origin); - if (charge.getChargeType() === ChargeType.Minus) { diff.multiplyScalar(-1); } + const cone = new THREE.Mesh(this.coneGeometry, this.coneMaterial); + cone.position.copy(origin); cone.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), diff.normalize()); this.add(cone); } } } + + // 電気力線を結合することで描画負荷を軽減 (draw call軽減) + const lineGeometry = BufferGeometryUtils.mergeGeometries(lines); + const line = new THREE.Mesh(lineGeometry, this.lineMaterial); + this.add(line); } update() { + // const start = performance.now(); + + // ジオメトリをすべて破棄 for (const child of this.children) { if (child instanceof THREE.Mesh) { @@ -81,6 +87,10 @@ class ElectricLines3D extends THREE.Object3D { } this.children = []; this.createELines(); + + + // const end = performance.now(); + // console.log(`update: ${end - start}ms`); } } @@ -89,7 +99,7 @@ class ElectricLines3D extends THREE.Object3D { /** * 電界 */ -class ElectricField { +export class ElectricField { /** @@ -197,43 +207,4 @@ class ElectricField { -} - -/// 電界 -export class Field3D extends THREE.Object3D { - - - private field: ElectricField; - private electricLines3d: THREE.Object3D; - - - /** - * コンストラクタ - * @param charges 電荷の配列 - */ - constructor(charges: Charge[]) { - super(); - this.field = new ElectricField(charges); - this.electricLines3d = new ElectricLines3D(this.field); - } - - - /** - * フィールドの更新 - */ - update = () => { - if (this.children.find((child) => child === this.electricLines3d) != null) - this.electricLines3d?.update(); - } - - - /** - * 電気力線の表示/非表示を切り替える - * @param visible 表示するかどうか - */ - enableElectricLines = (visible: boolean) => { - this.electricLines3d.visible = visible; - }; - - } diff --git a/app/script/main.ts b/app/script/main.ts index 5697e2e..3c7e404 100644 --- a/app/script/main.ts +++ b/app/script/main.ts @@ -2,7 +2,7 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import { Editor } from './editor'; import { Dragger } from './dragger'; -import { Field3D } from './field3d'; +import { ElectricField, ElectricLines3D } from './field3d'; import { throttle } from 'throttle-debounce'; import { Charge } from './charge'; import { PointCharge } from './pointCharge'; @@ -75,7 +75,7 @@ const start = () => { Store.RegisterChargeGenerator("InfinityCylinderSurfaceCharge", InfinityCylinderSurfaceCharge.fromJSON); } - + // 点電荷たち const charges: Charge[] = []; @@ -89,8 +89,8 @@ const start = () => { } // シミュレーション空間 - const field3d = new Field3D(charges); - scene.add(field3d); + const electricForceLine = new ElectricLines3D(new ElectricField(charges)); + scene.add(electricForceLine); // 電荷をドラッグして移動させるやつ const dragger = new Dragger(charges, camera, dom, controls, scene); @@ -103,7 +103,7 @@ const start = () => { parameterEditor = charge.createEditor(); parameterEditor.addEventListener('input', throttle(100, () => { - field3d.update(); + electricForceLine.update(); })); dragger.setMode('translate'); parameterEditor.addEventListener('position-editor', () => { @@ -116,16 +116,17 @@ const start = () => { parameterEditor.enable(); - field3d.update(); + electricForceLine.update(); } // 電荷が移動中 - dragger.addEventListener('object-change', throttle(100, () => { - field3d.update(); + dragger.addEventListener('object-change', throttle(50, () => { + electricForceLine.update(); })); - dragger.addEventListener('object-change', () => { + dragger.addEventListener('object-change', throttle(300, () => { + // パラメーター編集エディタの更新 parameterEditor.update(); - }); + })); // 電荷が選択された dragger.addEventListener('object-selected', (charge: Charge) => { @@ -144,13 +145,13 @@ const start = () => { dragger.attach(newCharge); parameterEditor.disable(); onSelected(newCharge); - field3d.update(); + electricForceLine.update(); } const deleteCharge = () => { if (dragger.getSelected()) { dragger.removeSelected(); - field3d.update(); + electricForceLine.update(); if (charges.length > 0) { // 電荷が残っている場合別の電化に再アタッチする @@ -235,9 +236,9 @@ const start = () => { // 電気力線 表示/非表示 { const checkbox = document.getElementById('checkbox_electric_lines') as HTMLInputElement; - field3d.enableElectricLines(checkbox.checked); // 初期値 + electricForceLine.visible = checkbox.checked; // 初期値 checkbox.addEventListener('change', (e) => { - field3d.enableElectricLines((e.target as HTMLInputElement).checked); + electricForceLine.visible = (e.target as HTMLInputElement).checked; }); } From c9dc3a43a0da18fa2ebf312c5ff819d07d54d109 Mon Sep 17 00:00:00 2001 From: Casey_Nelson <91818705+CaseyNelson314@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:47:04 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=B3=E3=82=82?= =?UTF-8?q?=E5=90=8C=E3=81=98=E3=81=8F=E3=82=B8=E3=82=AA=E3=83=A1=E3=83=88?= =?UTF-8?q?=E3=83=AA=E7=B5=B1=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/field3d.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/script/field3d.ts b/app/script/field3d.ts index 33025bb..b9a08df 100644 --- a/app/script/field3d.ts +++ b/app/script/field3d.ts @@ -11,7 +11,6 @@ export class ElectricLines3D extends THREE.Object3D { private field: ElectricField; private lineMaterial = new MeshLineMaterial({ color: new THREE.Color(0xffffff), lineWidth: 1 }) private coneMaterial = new THREE.MeshBasicMaterial({ color: 0xbbbbbb }); - private coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); constructor(field: ElectricField) { super(); @@ -22,6 +21,7 @@ export class ElectricLines3D extends THREE.Object3D { createELines() { const lines: MeshLineGeometry[] = []; + const cones: THREE.ConeGeometry[] = []; for (const charge of this.field.charges) { @@ -60,19 +60,24 @@ export class ElectricLines3D extends THREE.Object3D { diff.multiplyScalar(-1); } - const cone = new THREE.Mesh(this.coneGeometry, this.coneMaterial); - cone.position.copy(origin); - cone.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), diff.normalize()); - this.add(cone); + const coneGeometry = new THREE.ConeGeometry(1.5, 4, 10); + coneGeometry.applyQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), diff.normalize())); + coneGeometry.translate(origin.x, origin.y, origin.z); + cones.push(coneGeometry); } } } - // 電気力線を結合することで描画負荷を軽減 (draw call軽減) + // ジオメトリを結合し、描画負荷を軽減 (draw call削減) const lineGeometry = BufferGeometryUtils.mergeGeometries(lines); const line = new THREE.Mesh(lineGeometry, this.lineMaterial); this.add(line); + + const coneGeometry = BufferGeometryUtils.mergeGeometries(cones); + const cone = new THREE.Mesh(coneGeometry, this.coneMaterial); + this.add(cone); + } update() { From 7d8bf04871e028805d868a78737017b2ce6bf1bd Mon Sep 17 00:00:00 2001 From: Casey_Nelson <91818705+CaseyNelson314@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:51:48 +0900 Subject: [PATCH 7/8] =?UTF-8?q?HTML=E3=83=95=E3=82=A9=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E3=81=AE=E6=9B=B4=E6=96=B0=E9=80=9F=E5=BA=A6=E4=B8=8A=E3=81=92?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/script/main.ts b/app/script/main.ts index 3c7e404..72274c7 100644 --- a/app/script/main.ts +++ b/app/script/main.ts @@ -123,7 +123,7 @@ const start = () => { dragger.addEventListener('object-change', throttle(50, () => { electricForceLine.update(); })); - dragger.addEventListener('object-change', throttle(300, () => { + dragger.addEventListener('object-change', throttle(50, () => { // パラメーター編集エディタの更新 parameterEditor.update(); })); From 7370c361b8e1be277100a99595c9aa157ff773c7 Mon Sep 17 00:00:00 2001 From: Casey_Nelson <91818705+CaseyNelson314@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:52:48 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=E3=82=B7=E3=83=9F=E3=83=A5=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E7=A9=BA=E9=96=93=E3=81=AE?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=80=9F=E5=BA=A6=E8=90=BD=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/script/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/script/main.ts b/app/script/main.ts index 72274c7..e91a952 100644 --- a/app/script/main.ts +++ b/app/script/main.ts @@ -120,7 +120,7 @@ const start = () => { } // 電荷が移動中 - dragger.addEventListener('object-change', throttle(50, () => { + dragger.addEventListener('object-change', throttle(100, () => { electricForceLine.update(); })); dragger.addEventListener('object-change', throttle(50, () => {