|
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
|
|
<script src="data/lib/p5.min.js" type="text/javascript"></script>
|
|
|
|
<script src="data/lib/jquery-3.6.4.min.js" type="text/javascript"></script>
|
|
|
|
<script src="data/lib/vue.global.js"></script>
|
|
|
|
<script src="data/scripts/js/main.js" type="text/javascript"></script>
|
|
|
|
<link href="styles.css" rel="stylesheet">
|
|
|
|
<link href="data/styles/range_input.css" rel="stylesheet">
|
|
|
|
<title>Pendulum</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="p5_loading"></div>
|
|
|
|
<div id="content">
|
|
|
|
<div id="options">
|
|
|
|
<fieldset id="preparation">
|
|
|
|
<legend>Add Pendula</legend>
|
|
|
|
<label>
|
|
|
|
Segments: {{ segmentCount }}
|
|
|
|
<input type="range" v-model.number="segmentCount" min="1" max="30" step="1">
|
|
|
|
</label>
|
|
|
|
<div id="segment_view">
|
|
|
|
<span id="segment_header_mass">Mass</span><span id="segment_header_length">Length</span>
|
|
|
|
<template v-for="i in segmentCount">
|
|
|
|
<span class="segment_label">({{ i - 1 }})</span>
|
|
|
|
<span class="segment_label">{{ masses[i - 1] }}kg</span>
|
|
|
|
<input type="range" v-model.number="masses[i - 1]" min="0.1" max="10" step=".1">
|
|
|
|
<span class="segment_label">{{ $filters.round(lengths[i - 1], 1) }}m</span>
|
|
|
|
<input type="range" v-model.number="lengths[i - 1]" min="0.1" max="10" step=".1">
|
|
|
|
</template>
|
|
|
|
</div>
|
|
|
|
<div class="horizontal_group">
|
|
|
|
<button class="reset_btn" @click="resetMasses" title="Reset masses to 1"></button>
|
|
|
|
<button id="normalize_btn" @click="normalize" title="Normalize lengths to fit screen"></button>
|
|
|
|
<button class="reset_btn" @click="resetLengths" title="Reset lengths to 1"></button>
|
|
|
|
</div>
|
|
|
|
<label>
|
|
|
|
Starting Angle: {{startAngle}}°
|
|
|
|
<input type="range" v-model.number="startAngle" min="0" max="360" step="1">
|
|
|
|
</label>
|
|
|
|
<label v-show="!multiple || !rainbow">
|
|
|
|
Color:
|
|
|
|
<input type="color" v-model="color">
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input type="checkbox" v-model="multiple">
|
|
|
|
Add multiple
|
|
|
|
</label>
|
|
|
|
<template v-if="multiple">
|
|
|
|
<label>
|
|
|
|
<input type="checkbox" v-model="rainbow">
|
|
|
|
Use rainbow coloring
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
Count: {{pendulumCount}}
|
|
|
|
<input type="range" v-model.number="pendulumCount" min="10" max="250" step="10">
|
|
|
|
</label>
|
|
|
|
<span>Property to change slightly:</span>
|
|
|
|
<label>
|
|
|
|
<input type="radio" value="angle" v-model="changeProperty">
|
|
|
|
Starting Angle
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input type="radio" value="mass" v-model="changeProperty">
|
|
|
|
Specific Mass
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input type="radio" value="length" v-model="changeProperty">
|
|
|
|
Specific Length
|
|
|
|
</label>
|
|
|
|
<label v-show="changeProperty === 'mass' || changeProperty === 'length'">
|
|
|
|
Index: {{ changeIndex }}
|
|
|
|
<input type="range" v-model.number="changeIndex" min="0" :max="segmentCount - 1" step="1">
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
Change Amount: {{ $filters.round(changeAmount * 100, 3) }}%
|
|
|
|
<input type="range" v-model.number="changeAmount" min="0.00001" max="0.001" step="0.00001">
|
|
|
|
</label>
|
|
|
|
</template>
|
|
|
|
<div class="horizontal_group">
|
|
|
|
<button @click="add" id="add_btn" :title="'Add configured ' + (multiple ? 'pendula' : 'pendulum')"></button>
|
|
|
|
<button @click="deleteAll" id="delete_btn" title="Delete all pendula"></button>
|
|
|
|
</div>
|
|
|
|
</fieldset>
|
|
|
|
<fieldset id="simulation">
|
|
|
|
<legend>Simulation</legend>
|
|
|
|
<label>
|
|
|
|
Gravity: {{ gravity }} <sup>N</sup>⁄<sub>kg</sub>
|
|
|
|
<input type="range" v-model.number="gravity" min="0" max="30" step=".01">
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
Timescale: x{{ timescale }}
|
|
|
|
<input type="range" v-model.number="timescale" min="0.01" max="3" step=".01">
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
PBD Substeps: {{ subSteps }}
|
|
|
|
<input type="range" v-model.number="subSteps" min="1" max="100" step="1">
|
|
|
|
</label>
|
|
|
|
<div class="horizontal_group">
|
|
|
|
<button class="reset_btn" @click="resetSimulationControls" title="Reset simulation controls"></button>
|
|
|
|
<button @click="togglePlay" id="play_btn" :class="playingBtn" title="Pause/Resume simulation"></button>
|
|
|
|
</div>
|
|
|
|
</fieldset>
|
|
|
|
</div>
|
|
|
|
<div id="canvas_holder"></div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|