Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
vektor [2024/10/15 07:24] jango [Links] |
vektor [2024/12/07 17:32] (aktuell) jango [Vektor Visualisierung] |
||
---|---|---|---|
Zeile 74: | Zeile 74: | ||
* Besonders wichtig in der 3D Programmierung ist das **Kreuzprodukt**, | * Besonders wichtig in der 3D Programmierung ist das **Kreuzprodukt**, | ||
- | =====Dot product===== | + | =====Dot product |
- | siehe auch [[http:// | + | Das Dot-Produkt (auch Skalarprodukt genannt) ist eine mathematische Operation, die auf zwei Vektoren angewendet wird und einen Skalar (eine Zahl) als Ergebnis liefert. Es wird häufig verwendet, um den Winkel zwischen zwei Vektoren zu berechnen oder um zu überprüfen, |
- | Das [[https:// | + | Für zwei Vektoren |
- | Hat man 2 Koordinaten gegeben | + | A = (a1, a2, a3) |
+ | B = (b1, b2, b3) | ||
+ | |||
+ | im 3D-Raum lautet die Formel für das Dot-Produkt: | ||
+ | |||
+ | A * B = a1 + b1 + a2 * b2 + a3 * b3 | ||
+ | |||
+ | Die Berechnung des Dot-Produkts erfolgt durch die Multiplikation der entsprechenden Komponenten der beiden Vektoren | ||
+ | |||
+ | Geometrische Bedeutung: | ||
+ | Das Dot-Produkt lässt sich auch in Bezug auf den Winkel PHI zwischen den beiden Vektoren ausdrücken: | ||
+ | |||
+ | A⋅B=∣A∣⋅∣B∣⋅cos(θ) | ||
+ | |||
+ | ∣A∣ ist die Länge von Vektor | ||
+ | |||
+ | Das Dot-Produkt ist besonders nützlich, um zu bestimmen, ob zwei Vektoren in die gleiche Richtung zeigen: | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | Beispiel: | ||
+ | Nehmen wir die Vektoren A=(1,2,3) und B=(4, | ||
+ | |||
+ | Das Dot-Produkt ist: A⋅B=(1⋅4)+(2⋅−5)+(3⋅6)=4−10+18=12 | ||
+ | |||
+ | Das Ergebnis ist der Skalar 12. Dies bedeutet, dass die Vektoren in eine ähnliche Richtung zeigen. | ||
{{vektor_definieren.png}} | {{vektor_definieren.png}} | ||
+ | =====Cross product===== | ||
+ | |||
+ | Das Kreuzprodukt zweier Vektoren im 3D-Raum ergibt einen Vektor, der senkrecht (orthogonal) auf beiden Eingangsvektoren steht. | ||
+ | |||
+ | |||
+ | Für zwei Vektoren | ||
+ | |||
+ | A = (a1, a2, a3) | ||
+ | B = (b1, b2, b3) | ||
- | Das bedeutet umgekehrt | + | im 3D-Raum lautet die Formel für das Cross-Produkt: |
< | < | ||
- | Von 5 nach -1 => -6 | + | | i, j, k | |
- | Von 1 nach 5 => 4 | + | A * B = | a1, a2, a3 | |
- | Von -2 nach 1 => 3 | + | | b1, b2, b3 | |
</ | </ | ||
- | **Merke:** | + | |
+ | Dabei sind i,j,k die Einheitsvektoren entlang der x-, y- und z-Achse. | ||
- | * if dot > 0 => deg < 90 | + | Die Berechnung erfolgt durch die Determinante der Matrix, die die Komponenten der beiden Vektoren enthält. |
- | * if dot == 0 => deg == 90 | + | |
- | * if dot < 0 => deg > 90 | + | |
- | =====Cross product===== | + | |
- | siehe auch [[http:// | + | < |
+ | A * B = ((a2 * b3 - a3 * b2), (a3 * b1 - a1 * b3), (a1 * b2 - a2 * b1)) | ||
+ | </code> | ||
- | Das [[https:// | + | Das Cross-Produkt ergibt einen Vektor, der senkrecht |
+ | Die Länge des resultierenden Vektors entspricht der Fläche des Parallelogramms, | ||
- | Erst die violetten Verbindungen, | ||
{{kreuzprodukt.png}} | {{kreuzprodukt.png}} | ||
Zeile 129: | Zeile 165: | ||
https:// | https:// | ||
+ | |||
+ | =====Vektor Visualisierung===== | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <html lang=" | ||
+ | < | ||
+ | <meta charset=" | ||
+ | <meta name=" | ||
+ | < | ||
+ | < | ||
+ | body { margin: 0; font-family: | ||
+ | canvas { display: block; } | ||
+ | .controls { | ||
+ | position: absolute; | ||
+ | top: 10px; | ||
+ | left: 10px; | ||
+ | z-index: 1; | ||
+ | background: rgba(255, 255, 255, 0.7); | ||
+ | padding: 15px; | ||
+ | width: 240px; | ||
+ | height: 90%; | ||
+ | overflow-y: auto; | ||
+ | } | ||
+ | .section { | ||
+ | margin-bottom: | ||
+ | } | ||
+ | .section h3 { | ||
+ | margin-top: 0; | ||
+ | } | ||
+ | .section input, .section button { | ||
+ | width: 100%; | ||
+ | margin-bottom: | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | <div class=" | ||
+ | <!-- Vektor Eingabe --> | ||
+ | <div class=" | ||
+ | < | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <button onclick=" | ||
+ | </ | ||
+ | |||
+ | <!-- Vektor Operationen --> | ||
+ | <div class=" | ||
+ | < | ||
+ | <button onclick=" | ||
+ | <button onclick=" | ||
+ | <button onclick=" | ||
+ | </ | ||
+ | |||
+ | <!-- Rotation der Szene --> | ||
+ | <div class=" | ||
+ | < | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | <input type=" | ||
+ | </ | ||
+ | |||
+ | <!-- Kamera Position und Rotation --> | ||
+ | <div class=" | ||
+ | < | ||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <label for=" | ||
+ | <input type=" | ||
+ | |||
+ | <button onclick=" | ||
+ | <button onclick=" | ||
+ | </ | ||
+ | |||
+ | <!-- Ausgabe --> | ||
+ | <div class=" | ||
+ | <span id=" | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <script src=" | ||
+ | <script src=" | ||
+ | |||
+ | < | ||
+ | const scene = new THREE.Scene(); | ||
+ | const camera = new THREE.PerspectiveCamera(75, | ||
+ | const renderer = new THREE.WebGLRenderer(); | ||
+ | renderer.setSize(window.innerWidth, | ||
+ | document.body.appendChild(renderer.domElement); | ||
+ | |||
+ | const light = new THREE.AmbientLight(0x404040, | ||
+ | scene.add(light); | ||
+ | |||
+ | const directionalLight = new THREE.DirectionalLight(0xffffff, | ||
+ | directionalLight.position.set(5, | ||
+ | scene.add(directionalLight); | ||
+ | |||
+ | function zoomIn() { | ||
+ | if (camera.position.z > 1) { | ||
+ | camera.position.z -= 1; | ||
+ | renderer.render(scene, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function zoomOut() { | ||
+ | camera.position.z += 1; | ||
+ | renderer.render(scene, | ||
+ | } | ||
+ | |||
+ | let v1 = new THREE.Vector3(1, | ||
+ | let v2 = new THREE.Vector3(3, | ||
+ | |||
+ | let arrowV1, arrowV2, arrowResultant, | ||
+ | |||
+ | function createArrow(vector, | ||
+ | const arrowHelper = new THREE.ArrowHelper(vector.clone().normalize(), | ||
+ | scene.add(arrowHelper); | ||
+ | return arrowHelper; | ||
+ | } | ||
+ | |||
+ | function createAxisAndScale() { | ||
+ | var maxNum = 9999; | ||
+ | |||
+ | const xAxisGeometry = new THREE.BufferGeometry().setFromPoints([ | ||
+ | new THREE.Vector3(0, | ||
+ | new THREE.Vector3(maxNum, | ||
+ | ]); | ||
+ | const xAxisMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 }); | ||
+ | const xAxis = new THREE.Line(xAxisGeometry, | ||
+ | scene.add(xAxis); | ||
+ | |||
+ | const yAxisGeometry = new THREE.BufferGeometry().setFromPoints([ | ||
+ | new THREE.Vector3(0, | ||
+ | new THREE.Vector3(0, | ||
+ | ]); | ||
+ | const yAxisMaterial = new THREE.LineBasicMaterial({ color: 0x00ff00 }); | ||
+ | const yAxis = new THREE.Line(yAxisGeometry, | ||
+ | scene.add(yAxis); | ||
+ | |||
+ | const zAxisGeometry = new THREE.BufferGeometry().setFromPoints([ | ||
+ | new THREE.Vector3(0, | ||
+ | new THREE.Vector3(0, | ||
+ | ]); | ||
+ | const zAxisMaterial = new THREE.LineBasicMaterial({ color: 0x0000ff }); | ||
+ | const zAxis = new THREE.Line(zAxisGeometry, | ||
+ | scene.add(zAxis); | ||
+ | |||
+ | for (let i = 1; i <= maxNum; i++) { | ||
+ | const xMarker = new THREE.Mesh( | ||
+ | new THREE.SphereGeometry(0.1), | ||
+ | new THREE.MeshBasicMaterial({ color: 0xff0000 }) | ||
+ | ); | ||
+ | xMarker.position.set(i, | ||
+ | scene.add(xMarker); | ||
+ | |||
+ | const yMarker = new THREE.Mesh( | ||
+ | new THREE.SphereGeometry(0.1), | ||
+ | new THREE.MeshBasicMaterial({ color: 0x00ff00 }) | ||
+ | ); | ||
+ | yMarker.position.set(0, | ||
+ | scene.add(yMarker); | ||
+ | |||
+ | const zMarker = new THREE.Mesh( | ||
+ | new THREE.SphereGeometry(0.1), | ||
+ | new THREE.MeshBasicMaterial({ color: 0x0000ff }) | ||
+ | ); | ||
+ | zMarker.position.set(0, | ||
+ | scene.add(zMarker); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function updateVectors() { | ||
+ | v1.set( | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | ); | ||
+ | |||
+ | v2.set( | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | ); | ||
+ | |||
+ | scene.clear(); | ||
+ | |||
+ | createAxisAndScale(); | ||
+ | |||
+ | arrowV1 = createArrow(v1, | ||
+ | arrowV2 = createArrow(v2, | ||
+ | |||
+ | if (arrowResultant) scene.remove(arrowResultant); | ||
+ | if (arrowDifference) scene.remove(arrowDifference); | ||
+ | if (arrowCrossProduct) scene.remove(arrowCrossProduct); | ||
+ | |||
+ | displayVectorComponents(v1, | ||
+ | displayVectorComponents(v2, | ||
+ | |||
+ | renderer.render(scene, | ||
+ | } | ||
+ | |||
+ | function toggleResultant() { | ||
+ | if (arrowResultant) { | ||
+ | scene.remove(arrowResultant); | ||
+ | arrowResultant = null; | ||
+ | } else { | ||
+ | arrowResultant = createArrow(v1.clone().add(v2), | ||
+ | displayVectorComponents(v1.clone().add(v2), | ||
+ | renderer.render(scene, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDifference() { | ||
+ | if (arrowDifference) { | ||
+ | scene.remove(arrowDifference); | ||
+ | arrowDifference = null; | ||
+ | } else { | ||
+ | arrowDifference = createArrow(v1.clone().sub(v2), | ||
+ | displayVectorComponents(v1.clone().sub(v2), | ||
+ | renderer.render(scene, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleCrossProduct() { | ||
+ | if (arrowCrossProduct) { | ||
+ | scene.remove(arrowCrossProduct); | ||
+ | arrowCrossProduct = null; | ||
+ | } else { | ||
+ | arrowCrossProduct = createArrow(v1.clone().cross(v2), | ||
+ | displayVectorComponents(v1.clone().cross(v2), | ||
+ | renderer.render(scene, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function displayVectorComponents(vector, | ||
+ | const output = document.getElementById(' | ||
+ | const outputText = `${label} - x: ${vector.x.toFixed(2)}, | ||
+ | output.textContent = outputText; | ||
+ | console.log(outputText); | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | camera.position.x = document.getElementById(" | ||
+ | camera.position.y = document.getElementById(" | ||
+ | camera.position.z = document.getElementById(" | ||
+ | */ | ||
+ | |||
+ | function animate() { | ||
+ | requestAnimationFrame(animate); | ||
+ | |||
+ | scene.rotation.x = document.getElementById(' | ||
+ | scene.rotation.y = document.getElementById(' | ||
+ | scene.rotation.z = document.getElementById(' | ||
+ | |||
+ | renderer.render(scene, | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | camera.position.set( | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | ); | ||
+ | |||
+ | camera.rotation.set( | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | parseFloat(document.getElementById(' | ||
+ | ); | ||
+ | |||
+ | renderer.render(scene, | ||
+ | } | ||
+ | |||
+ | window.addEventListener(' | ||
+ | renderer.setSize(window.innerWidth, | ||
+ | camera.aspect = window.innerWidth / window.innerHeight; | ||
+ | camera.updateProjectionMatrix(); | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | scene.rotation.x = this.value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | scene.rotation.y = this.value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | scene.rotation.z = this.value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | const value = parseFloat(this.value); | ||
+ | scene.rotation.x = value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | const value = parseFloat(this.value); | ||
+ | scene.rotation.y = value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | const value = parseFloat(this.value); | ||
+ | scene.rotation.z = value * Math.PI / 180; | ||
+ | document.getElementById(' | ||
+ | }); | ||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | animate(); | ||
+ | updateVectors(); | ||
+ | updateCamera(); | ||
+ | |||
+ | //for(var i = 0; i<5; i++) zoomOut(); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
=====Links===== | =====Links===== |