Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/change dimension #1

Merged
merged 5 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,41 @@
<meta charset="utf-8" />
<title>EFSim</title>
<link rel="stylesheet" href="style/style.css" />
<link rel="stylesheet" href="style/toggle.css" />
<link rel="icon" href="static/kagaku_genshi.png" />
</head>
<body>
<script type="module" src="script/main.js"></script>
<div class="app">
<div id="canvas"></div>
<div class="settings">
<div class="enable_auto_rotate">
<input type="checkbox" id="checkbox_auto_rotate" checked />
<label for="checkbox_auto_rotate">自動回転</label>
<label class="dimension_toggle">
<input type="checkbox" id="dimension_toggle_switch" checked/>
<div id="dimension_toggle_slider">3D</div>
</label>
<!-- <div class="settings_2d">
<label class="checkbox">
<input type="checkbox" id="checkbox_electric_field_vectors" />
電界ベクトル
</label>
<label class="checkbox">
<input type="checkbox" id="checkbox_electric_field_vectors" />
電気力線
</label> -->
<div class="settings_3d">
<label class="checkbox">
<input type="checkbox" id="checkbox_auto_rotate" checked />
自動回転
</label>
<label class="checkbox">
<input type="checkbox" id="checkbox_electric_field_vectors"/>
電界ベクトル
</label>
<label class="checkbox">
<input type="checkbox" id="checkbox_electric_lines" checked/>
電気力線
</label>
</div>
<div class="enable_electric_field_vectors">
<input type="checkbox" id="checkbox_electric_field_vectors" />
<label for="checkbox_electric_field_vectors">電場ベクトル</label>
</div>
</div>
</div>
</body>
</html>
185 changes: 185 additions & 0 deletions app/script/Field3D.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import * as THREE from "three";
import PointCharge from "./PointCharge.js";

// 指定座標における電場ベクトルを計算
export const PosToElectricFieldVector = (pos, point_charges) => {
var electric_field_vector = new THREE.Vector3(0, 0, 0); // 合成ベクトル
for (const point_charge of point_charges) {
const diff = new THREE.Vector3(0, 0, 0);
diff.subVectors(pos, point_charge.pos); // 点電荷と観測点との差分ベクトル

const r_sq = diff.lengthSq(); // 点電荷と観測点との距離^2 (平方根処理をなくすため)
const k = 8.987552 * 10 ** 9; // クーロン定数

const factor = r_sq ? (k * point_charge.charge) / r_sq ** 2 : 0; // ベクトルにかける係数

diff.multiplyScalar(factor);

electric_field_vector.add(diff);
}
return electric_field_vector;
};

/// 電気力線
class ElectricLines3D extends THREE.Group {
constructor(point_charges) {
super();
this.point_charges = point_charges;
this.createField(point_charges);
}

/// @param origin 始点 (PointCharge)
createElectricLineGeometry = (
origin_charge,
vector,
point_charges,
length
) => {
const points = [origin_charge.pos.clone()];
const _origin = origin_charge.pos.clone();
_origin.add(vector);
for (var i = 0; i < length; i++) {
const d_vector = PosToElectricFieldVector(_origin, point_charges);
d_vector.normalize();
if (origin_charge.charge < 0) d_vector.multiplyScalar(-1);
// 点電荷との衝突判定
for (const point_charge of point_charges) {
const diff = new THREE.Vector3(0, 0, 0);
diff.subVectors(_origin, point_charge.pos);
if (diff.length() < 1) {
return new THREE.BufferGeometry().setFromPoints(points);
}
}
_origin.add(d_vector);
points.push(_origin.clone());
}
return new THREE.BufferGeometry().setFromPoints(points);
};

createField(point_charges) {
const line_material = new THREE.LineBasicMaterial({ color: 0xaaaaff });
for (const point_charge of point_charges) {
for (var n_theta = 0; n_theta < 5; n_theta++) {
for (var n_phi = 0; n_phi < 5; n_phi++) {
const theta = ((Math.PI * 2) / 5) * n_theta;
const phi = ((Math.PI * 2) / 5) * n_phi;
const x = 5 * Math.sin(theta) * Math.cos(phi);
const y = 5 * Math.sin(theta) * Math.sin(phi);
const z = 5 * Math.cos(theta);

const line = new THREE.Line(
this.createElectricLineGeometry(
point_charge,
new THREE.Vector3(x, y, z),
point_charges,
1000
),
line_material
);
this.add(line);
}
}
}
}
}

// 点電荷
class PointCharges3D extends THREE.Group {
constructor(point_charges) {
super();
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material_minus = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const material_plus = new THREE.MeshBasicMaterial({ color: 0xff0000 });
for (const point_charge of point_charges) {
const material = point_charge.charge > 0 ? material_plus : material_minus;
const sphere = new THREE.Mesh(geometry, material);
sphere.position.copy(point_charge.pos);
this.add(sphere);
}
}
}

// 電界ベクトル
class ElectricFieldVectors3D extends THREE.Group {
constructor(point_charges) {
super();
this.point_charges = point_charges;

for (var point_charge of point_charges) {
for (var x = -4; x <= 4; x++) {
for (var y = -4; y <= 4; y++) {
for (var z = -4; z <= 4; z++) {
if (x ** 2 + y ** 2 + z ** 2 > 5 ** 2) continue;
if (x === 0 && y === 0 && z === 0) continue;
const origin = new THREE.Vector3(x * 10, y * 10, z * 10);
origin.add(point_charge.pos);
const electric_field_vector = PosToElectricFieldVector(
origin,
point_charges
);

const len = electric_field_vector.length();
this.add(
new THREE.ArrowHelper(
electric_field_vector.normalize(),
origin,
1,
0xffffff,
2,
0.5
)
);
}
}
}
}
}
}

/// 電界
export class Field3D extends THREE.Group {
constructor(point_charges) {
super();
this.point_charges = point_charges;
this.enablePointCharges(true);
}

point_charges_3d = null;
electric_lines_3d = null;
electric_field_vectors_3d = null;

/// 点電荷の表示切替
enablePointCharges = (enable) => {
if (enable) {
if (this.point_charges_3d == null)
this.point_charges_3d = new PointCharges3D(this.point_charges);
this.add(this.point_charges_3d);
} else {
this.remove(this.point_charges_3d);
}
};

/// 電気力線の表示切替
enableElectricLines = (enable) => {
if (enable) {
if (this.electric_lines_3d == null)
this.electric_lines_3d = new ElectricLines3D(this.point_charges);
this.add(this.electric_lines_3d);
} else {
this.remove(this.electric_lines_3d);
}
};

/// 電界ベクトルの表示切替
enableElectricFieldVectors = (enable) => {
if (enable) {
if (this.electric_field_vectors_3d == null)
this.electric_field_vectors_3d = new ElectricFieldVectors3D(
this.point_charges
);
this.add(this.electric_field_vectors_3d);
} else {
this.remove(this.electric_field_vectors_3d);
}
};
}
20 changes: 17 additions & 3 deletions app/script/Init.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { TransformControls } from "three/addons/controls/TransformControls";

// シーンを作成
export const CreateScene = () => {
Expand Down Expand Up @@ -45,13 +46,26 @@ export const CreateCamera = () => {
};

// マウスコントロールを作成
export const CreateControls = (camera, renderer) => {
const controls = new OrbitControls(camera, renderer.domElement);
export const CreateControls = (camera, dom) => {
const controls = new OrbitControls(camera, dom);

controls.autoRotate = true; // 自動回転
controls.autoRotateSpeed = 1; // 自動回転の速度
controls.enableDamping = true; // 視点の移動を滑らかにする
controls.dampingFactor = 0.5; // 滑らか度合い
controls.dampingFactor = 0.2; // 滑らか度合い

return controls;
};

export const CreateTransformControls = (camera, dom, controls, scene) => {
const transControls = new TransformControls(camera, dom);

transControls.addEventListener("dragging-changed", (event) => {
controls.enablePan = !event.value;
controls.enableRotate = !event.value;
});

scene.add(transControls);

return transControls;
};
Loading
Loading