Hong-Phuc Bui
2026-10-18 94811ea59ca1b8f07284444736b6cc2eb4b35617
Interactive UI
1 files added
2 files modified
63 ■■■■■ changed files
02-0-kurswinkel-benutzer-interactive/index.html 2 ●●●●● patch | view | raw | blame | history
02-0-kurswinkel-benutzer-interactive/sphere-calculator.js 27 ●●●●● patch | view | raw | blame | history
02-0-kurswinkel-benutzer-interactive/tangente.js 34 ●●●●● patch | view | raw | blame | history
02-0-kurswinkel-benutzer-interactive/index.html
@@ -23,6 +23,6 @@
        </div>
    </div>
</div>
<script src="tangente.js"></script>
<script type="module" src="tangente.js"></script>
</body>
</html>
02-0-kurswinkel-benutzer-interactive/sphere-calculator.js
New file
@@ -0,0 +1,27 @@
export const toRadians = (deg) => deg * Math.PI / 180;
export const toDegrees = (rad) => rad * 180 / Math.PI;
export const azimuth = (longitude1, latitude1, longitude2, latitude2) =>{
    const [lon1, lat1, lon2, lat2] = [longitude1, latitude1, longitude2, latitude2].map(toRadians);
    const _deltaLon = Math.abs(lon2 - lon1);
    const PI = Math.PI;
    const deltaLon = (_deltaLon) <= PI ? _deltaLon : 2*PI - _deltaLon;
    const q = (Math.tan(PI/4 + lat2/2))/(Math.tan(PI/4 + lat1/2));
    const ln = 1/Math.log(q);
    const alpha = Math.atan( deltaLon*ln ) * 180/PI; // degree!
    const eastCourse = _deltaLon <= PI;
    const direction = ( lon2>=lon1 &&  eastCourse) || (lon2<lon1 && !eastCourse);
    if(lat2 > lat1 && direction) {
        return alpha;
    } else if(lat2 < lat1 && direction) {
        return 180 - alpha;
    } else if(lat2 < lat1 && !direction) {
        return 180 + alpha;
    } else if(lat2 > lat1 && !direction) {
        return 360 - alpha;
    }
    if(lat2 === lat1) {
        return direction ? 90 : 270;
    }
}
02-0-kurswinkel-benutzer-interactive/tangente.js
@@ -1,3 +1,5 @@
import {azimuth} from "./sphere-calculator.js";
const toXYZ = (longitude, latitude) => {
    const lon = (longitude * Math.PI) / 180;
    const lat = (latitude * Math.PI) / 180;
@@ -40,6 +42,11 @@
    return `${ lon.toFixed(1) }°|${ lat.toFixed(1)}°`;
}
const solveProjectionPoint = (startX, startY, startZ, targetX, targetY, targetZ) => {
    const t = targetX*targetX + targetY*targetY + targetZ*targetZ;
    const k = -(startX*targetX + startY*targetY + startZ*targetZ - t) / t;
    return [targetX + k * startX, targetY + k*startY, targetZ + k*startZ]
}
// board commands
const RADIUS = 6;
@@ -70,6 +77,14 @@
    {name: "Ziel LAT.", precision: 2}
);
const displayAzimuth = () => {
    const a = azimuth(startLongitude.Value(), startLatitude.Value(),
        targetLongitude.Value(), targetLatitude.Value()
    );
    return `Kurswinkel: ${a.toFixed(2)}°`;
}
const azimuthText = board.create('text', [8,6, displayAzimuth], {});
const view = board.create('view3d',
    [[-10, -10], [19, 19],
@@ -86,7 +101,9 @@
    }
);
const origin = view.create('point3d', [0,0,0], {name:"O", fixed: true});
const origin = view.create('point3d', [0,0,0],
    {name:"O", fixed: true, highlight: false, showInfobox: false,}
);
const earth = view.create('sphere3d', [origin, RADIUS]);
const NORTH_POLE = [0, 90];
@@ -118,11 +135,17 @@
const targetPoint = view.create('point3d',
    () => [...toXYZ(targetLongitude.Value(), targetLatitude.Value())],
    {id: 'T', fixed: true, highlight: true, showInfobox: false,
});
    {id: 'T', fixed: true, highlight: true, showInfobox: false,}
);
targetPoint.element2D.label.setText( () => "Ziel: " +
    toGeographicLabel( ...toLonLat(targetPoint.X(), targetPoint.Y(), targetPoint.Z()  ) ) );
const projectionPoint = view.create('point3d',
    () => solveProjectionPoint(
        startPoint.X(), startPoint.Y(), startPoint.Z(),
        targetPoint.X(), targetPoint.Y(), targetPoint.Z()
    ),
    {id: 'P', name:"Prj. Ziel", fixed: true, highlight: true, showInfobox: false, strokeColor:"black", fillColor: "gray"}
);
const routeNormalVector = () => {
    return normalVector(
@@ -139,7 +162,8 @@
const projectionDirectionVector = () => [startPoint.X(), startPoint.Y(), startPoint.Z()];
const projectionLine = view.create('line3d',
    [targetPoint, projectionDirectionVector,  [0, Infinity] ]
    [targetPoint, projectionDirectionVector,  [0, Infinity]],
    {strokeColor: "gray", dash: 2, strokeWidth: 1}
);