feature: add interactive applets
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
<html>
|
||||
<script src="https://www.50ohm.de/assets/jquery/3.7.1/jquery.min.js"></script>
|
||||
<p>Hier kann man das Ganze interaktiv ausprobieren. Wenn der Abstrahlwinkel flach ist steigt die Reichweite. Ist der Abstrahlwinkel steil, so verkürzt sich die Reichweite.</p><br>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
Abstrahlwinkel $\alpha$:
|
||||
</td>
|
||||
<td>
|
||||
<input type="range" class="slider" value="0" min="0" max="90" id="beamAngle">
|
||||
</td>
|
||||
<td>
|
||||
<div id="beamAngleField" style="display:inline-block;">0</div> °.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<canvas id="myCanvas" style="border:0px; width:100%; display: block;">
|
||||
Sorry, your browser does not support canvas.
|
||||
</canvas>
|
||||
|
||||
<script>
|
||||
|
||||
// Setup Canvas:
|
||||
const canvas = document.getElementById("myCanvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// Functions:
|
||||
function Vector(x, y) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
}
|
||||
|
||||
Vector.prototype = {
|
||||
ort: function() {
|
||||
return new Vector(this.y,-this.x);
|
||||
},
|
||||
add: function(v) {
|
||||
return new Vector(this.x + v.x, this.y + v.y);
|
||||
},
|
||||
rotate : function(angle) {
|
||||
return new Vector(
|
||||
Math.cos(angle)*this.x - Math.sin(angle)*this.y,
|
||||
Math.sin(angle)*this.x + Math.cos(angle)*this.y
|
||||
);
|
||||
},
|
||||
sp: function(v) {
|
||||
return this.x * v.x + this.y * v.y;
|
||||
},
|
||||
factor: function(f) {
|
||||
return new Vector(f*this.x, f*this.y);
|
||||
},
|
||||
length : function () {
|
||||
return Math.sqrt(this.x*this.x+this.y*this.y);
|
||||
},
|
||||
norm : function() {
|
||||
return new Vector(this.x/this.length(),this.y/this.length());
|
||||
},
|
||||
negate : function() {
|
||||
return new Vector(-1*this.x, -1*this.y);
|
||||
},
|
||||
angle: function(a) {
|
||||
return Math.acos(this.sp(a) / (this.length() * a.length()));
|
||||
},
|
||||
clone: function() {
|
||||
return new Vector(this.x, this.y);
|
||||
},
|
||||
};
|
||||
|
||||
function intersectionCircle(s, r, radius) {
|
||||
// I'm already proud of the derivation :-P So my Abi wasn't in vain after all
|
||||
sp = s.sp(r);
|
||||
lambda1 = -1*(sp) + Math.sqrt(Math.pow(sp,2)-s.sp(s)+Math.pow(radius,2));
|
||||
return s.add(r.factor(lambda1));
|
||||
}
|
||||
|
||||
function intersectionCircle2(s, r, radius) {
|
||||
// I'm already proud of the derivation :-P So my Abi wasn't in vain after all
|
||||
sp = s.sp(r);
|
||||
lambda2 = -1*(sp) - Math.sqrt(Math.pow(sp,2)-s.sp(s)+Math.pow(radius,2));
|
||||
return s.add(r.factor(lambda2));
|
||||
}
|
||||
|
||||
function drawLine(ctx, start, end, strokecolor, lineWidth) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(start.x, start.y);
|
||||
ctx.lineTo(end.x, end.y);
|
||||
ctx.lineWidth = lineWidth;
|
||||
if(strokecolor != "") {
|
||||
ctx.strokeStyle = strokecolor;
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawCircle(ctx, origin, radius, fillcolor, strokecolor, lineWidth){
|
||||
ctx.beginPath();
|
||||
ctx.arc(origin.x, origin.y, radius, 0, 2 * Math.PI, false);
|
||||
if(fillcolor != "") {
|
||||
ctx.fillStyle = fillcolor;
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.lineWidth = lineWidth;
|
||||
if(strokecolor != "") {
|
||||
ctx.strokeStyle = strokecolor;
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawArc(ctx, origin, radius, angle, fillcolor, strokecolor, lineWidth){
|
||||
ctx.beginPath();
|
||||
ctx.arc(origin.x, origin.y, radius, Math.PI/4, Math.PI/4+angle*Math.PI/180, false);
|
||||
if(fillcolor != "") {
|
||||
ctx.fillStyle = fillcolor;
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.lineWidth = lineWidth;
|
||||
if(strokecolor != "") {
|
||||
ctx.strokeStyle = strokecolor;
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
|
||||
function drawScene(ctx, angle) {
|
||||
|
||||
// Clean Canvas:
|
||||
ctx.canvas.width = 600;
|
||||
ctx.canvas.height = 200;
|
||||
|
||||
// Set origin to center:
|
||||
ctx.translate(canvas.width * 0.5, canvas.height * 1);
|
||||
|
||||
// Flip Canvas to normal:
|
||||
ctx.scale(1, -1);
|
||||
|
||||
// Origin:
|
||||
M = new Vector(0,0);
|
||||
|
||||
// Set Radius
|
||||
var radiusEarth = 100;
|
||||
var radiusAtmosphere = 180;
|
||||
|
||||
// Sender Point:
|
||||
S = new Vector(-radiusEarth/Math.sqrt(2),radiusEarth/Math.sqrt(2));
|
||||
|
||||
// Draw Antenna:
|
||||
antennaTop = S.factor(1.2);
|
||||
antennaMiddle = S.factor(1.1);
|
||||
antennaRadius = antennaTop.length();
|
||||
drawLine(ctx,S, antennaTop, "#000000", 1);
|
||||
ast1 = S.rotate(0.75*Math.PI).norm();
|
||||
ast2 = S.rotate(0.25*Math.PI).norm();
|
||||
end1 = intersectionCircle2(antennaMiddle, ast1, antennaRadius);
|
||||
end2 = intersectionCircle(antennaMiddle, ast2, antennaRadius);
|
||||
drawLine(ctx, antennaMiddle, end1, "#000000", 1);
|
||||
drawLine(ctx, antennaMiddle, end2, "#000000", 1);
|
||||
|
||||
// Create Vector nomalized orthogonal to the Senderpoint:
|
||||
Sorth = S.ort().norm();
|
||||
|
||||
// Draw Earth and Atmosphere:
|
||||
drawCircle(ctx, M, radiusEarth, "#49ace9", "", 1);
|
||||
drawCircle(ctx, M, radiusAtmosphere, "", "#ffbab5", 25);
|
||||
|
||||
// Rotate this normalized vector with the beaming angle:
|
||||
beam1 = Sorth.rotate(angle*Math.PI/180);
|
||||
|
||||
// Create the point where the beam intersects with the Atmosphere
|
||||
cp1 = intersectionCircle(S, beam1, radiusAtmosphere);
|
||||
|
||||
// Draw beam 1:
|
||||
drawLine(ctx, S, cp1, "#fe756c", 3);
|
||||
|
||||
// Calculate the angle between cp1neg and beam 1 neg:
|
||||
cbAngle = cp1.angle(beam1);
|
||||
|
||||
// Calculate cp1neg:
|
||||
cp1neg = cp1.negate();
|
||||
|
||||
// Rotate cp1neg by the cbAngle and normalize it:
|
||||
beam2 = cp1neg.rotate(cbAngle).norm();
|
||||
|
||||
// Create the point where the beam intersects with the Earth Circle
|
||||
cp2 = intersectionCircle2(cp1, beam2, radiusEarth);
|
||||
|
||||
// Draw beam 2:
|
||||
drawLine(ctx, cp1, cp2, "#fe756c", 3);
|
||||
|
||||
// Create the point where ground reference intersects with Atmosphere
|
||||
gp1 = intersectionCircle(S, Sorth, radiusAtmosphere);
|
||||
drawLine(ctx, S, gp1, "#999999", 1);
|
||||
gp2 = intersectionCircle2(S, Sorth, radiusAtmosphere);
|
||||
drawLine(ctx, S, gp2, "#999999", 1);
|
||||
|
||||
// Draw Angle
|
||||
drawArc(ctx, S, 40, angle, "", "#999999", 1);
|
||||
}
|
||||
|
||||
drawScene(ctx, 0);
|
||||
|
||||
$("#beamAngle").on("change", function() {
|
||||
console.log("DRAW");
|
||||
angle = $(this).val();
|
||||
drawScene(ctx, angle);
|
||||
$('#beamAngleField').html(angle);
|
||||
});
|
||||
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user