fixed stuff and improved the rendering engine by making inline math available using $$ and for ml $$\ncontent\n$$
This commit is contained in:
@@ -1,29 +1,41 @@
|
|||||||
# latex_extension.py
|
|
||||||
import marko
|
import marko
|
||||||
import marko.block
|
import marko.block
|
||||||
import marko.inline
|
import marko.inline
|
||||||
from marko.md_renderer import MarkdownRenderer
|
|
||||||
import re
|
import re
|
||||||
from log.Logger import Logger
|
from log.Logger import Logger
|
||||||
|
|
||||||
logger = Logger()
|
logger = Logger()
|
||||||
|
|
||||||
class BlockFormula(marko.block.BlockElement):
|
class BlockFormula(marko.block.BlockElement):
|
||||||
pattern = re.compile(r"\$\$ *\n([\s\S]+?)^\$\$ *$", re.MULTILINE)
|
pattern = re.compile(r"^\$\$\s*\n?([\s\S]+?)\n?\$\$\s*$", re.MULTILINE)
|
||||||
|
|
||||||
def __init__(self, match):
|
def __init__(self, match):
|
||||||
logger.log_debug("Did shit at __init__ for blockformula")
|
self.children = [marko.inline.RawText(match.group(1).strip())]
|
||||||
self.children = [marko.inline.RawText(match.group(1))]
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def match(cls, source):
|
def match(cls, source):
|
||||||
return source.expect_re(cls.pattern)
|
return source.expect_re(cls.pattern)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, source):
|
def parse(cls, source):
|
||||||
logger.log_debug("Did some shit with Latex")
|
|
||||||
match = source.match
|
match = source.match
|
||||||
source.consume()
|
source.consume()
|
||||||
return match
|
return match
|
||||||
|
|
||||||
|
class InlineFormula(marko.inline.InlineElement):
|
||||||
|
pattern = re.compile(r"\$(?!\$)([^\$]+?)\$")
|
||||||
|
parse_children = False # Math content is raw text
|
||||||
|
|
||||||
|
def __init__(self, match):
|
||||||
|
self.children = [marko.inline.RawText(match.group(1).strip())]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def match(cls, source):
|
||||||
|
return source.expect_re(cls.pattern)
|
||||||
|
|
||||||
class Paragraph(marko.block.Paragraph):
|
class Paragraph(marko.block.Paragraph):
|
||||||
override = True
|
override = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def break_paragraph(cls, source, lazy=False):
|
def break_paragraph(cls, source, lazy=False):
|
||||||
if BlockFormula.match(source):
|
if BlockFormula.match(source):
|
||||||
@@ -32,11 +44,16 @@ class Paragraph(marko.block.Paragraph):
|
|||||||
|
|
||||||
class Renderer:
|
class Renderer:
|
||||||
def render_block_formula(self, element):
|
def render_block_formula(self, element):
|
||||||
# Render as HTML with MathJax-compatible format
|
# MathJax compatible block math
|
||||||
return '\n<div class="math-block">$$\n' + self.render_children(element) + '$$</div>\n'
|
logger.log_debug(f"render_block_formula@LaTeXRenderer.py returned => {element}")
|
||||||
|
return f'\n<div class="math-block">$$\n{self.render_children(element)}\n$$</div>\n'
|
||||||
|
|
||||||
|
def render_inline_formula(self, element):
|
||||||
|
# MathJax compatible inline math
|
||||||
|
logger.log_debug(f"render_inline_formula@LaTeXRenderer.py returned => {element}")
|
||||||
|
return f'\\({self.render_children(element)}\\)'
|
||||||
|
|
||||||
class LaTeXExtension:
|
class LaTeXExtension:
|
||||||
logger.log_debug("Did shit at __init__ for latexextension")
|
elements = [BlockFormula, InlineFormula, Paragraph]
|
||||||
elements = [BlockFormula, Paragraph]
|
|
||||||
parser_mixins = []
|
parser_mixins = []
|
||||||
renderer_mixins = [Renderer]
|
renderer_mixins = [Renderer]
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
<script>
|
<script>
|
||||||
console.log("javascript is enabled! good!");
|
console.log("javascript is enabled! good!");
|
||||||
document.write('<h1 id="nojs" style="display: flex; align-items: center; cursor: pointer;" onclick="toggleDarkMode();"><img src="../../css/icons/folder.webp" alt="Folder icon" />Index of PyPost</h1>');
|
document.write('<h1 id="nojs" style="display: flex; align-items: center; cursor: pointer;" onclick="toggleDarkMode();"><img src="../../css/icons/folder.webp" alt="Folder icon" />Index of PyPost</h1>');
|
||||||
toggleDarkMode()
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -9,18 +9,16 @@
|
|||||||
<script src="../js/post/download.js" defer></script>
|
<script src="../js/post/download.js" defer></script>
|
||||||
|
|
||||||
<!-- Prism.js CSS theme -->
|
<!-- Prism.js CSS theme -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.min.css" rel="stylesheet" />
|
<link rel="preload" href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Prism.js core + languages -->
|
<!-- Prism.js core + languages -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
|
<script rel="preload" src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-python.min.js"></script>
|
<script rel="preload" src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-python.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-javascript.min.js"></script>
|
<script rel="preload" src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-javascript.min.js"></script>
|
||||||
|
|
||||||
<!-- JSZip for downloading the files as ZIP -->
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.11.0/jszip.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script>
|
<!-- MathJAX for LaTeX Support -->
|
||||||
|
<script rel="preload" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script>
|
||||||
|
|
||||||
<!-- remove if causing issues -->
|
<!-- remove if causing issues -->
|
||||||
<script src="../js/post/lazyimg.js"></script>
|
<script src="../js/post/lazyimg.js"></script>
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* We autoset the CSS to darkmode if no choice is in localstorage
|
||||||
|
* Else we allow White styles cause it doesnt look too bad
|
||||||
|
*/
|
||||||
function toggleDarkMode() {
|
function toggleDarkMode() {
|
||||||
document.body.classList.toggle("dark-mode");
|
document.body.classList.toggle("dark-mode");
|
||||||
localStorage.setItem("dark-mode", document.body.classList.contains("dark-mode"));
|
localStorage.setItem("dark-mode", document.body.classList.contains("dark-mode"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply stored preference when the page loads
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
if (localStorage.getItem("dark-mode") === "true") {
|
const stored = localStorage.getItem("dark-mode");
|
||||||
|
|
||||||
|
if (stored === null || stored === "true") {
|
||||||
document.body.classList.add("dark-mode");
|
document.body.classList.add("dark-mode");
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove("dark-mode");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2,127 +2,194 @@
|
|||||||
summary: "Würfelrotation mit Matrizen die Multipliziert werden erkläret"
|
summary: "Würfelrotation mit Matrizen die Multipliziert werden erkläret"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Rotation eines Würfels um die x-Achse
|
# Rotation eines Würfels mit Matrizen
|
||||||
|
|
||||||
Wir wollen verstehen, wie man einen Würfel im Raum um die x-Achse dreht.
|
## 1. Der Würfel im Raum
|
||||||
|
|
||||||
## 1. Punkte eines Würfels
|
Ein Würfel im Ursprung des Koordinatensystems (Mittelpunkt bei ( (0,0,0) )) und der Kantenlänge 2 besitzt die Eckpunkte:
|
||||||
|
|
||||||
Ein Würfel hat 8 Eckpunkte. Wenn wir den Würfel in der Mitte des Koordinatensystems platzieren, können wir die Punkte als Vektoren schreiben:
|
|
||||||
|
|
||||||
$$
|
$$
|
||||||
\mathbf{A} = (1, 1, 1), \quad
|
\begin{aligned}
|
||||||
\mathbf{B} = (1, 1, -1), \quad
|
A &= (1, 1, 1), & B &= (1, 1, -1), & C &= (1, -1, 1), \\
|
||||||
\mathbf{C} = (1, -1, 1), \quad
|
D &= (1, -1, -1), & E &= (-1, 1, 1), & F &= (-1, 1, -1), \\
|
||||||
\mathbf{D} = (1, -1, -1)
|
G &= (-1, -1, 1), & H &= (-1, -1, -1)
|
||||||
|
\end{aligned}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
|
Jeder Punkt kann als Spaltenvektor dargestellt werden:
|
||||||
$$
|
$$
|
||||||
\mathbf{E} = (-1, 1, 1), \quad
|
\mathbf{v} =
|
||||||
\mathbf{F} = (-1, 1, -1), \quad
|
|
||||||
\mathbf{G} = (-1, -1, 1), \quad
|
|
||||||
\mathbf{H} = (-1, -1, -1)
|
|
||||||
$$
|
|
||||||
|
|
||||||
Jeder Punkt hat drei Koordinaten
|
|
||||||
$$
|
|
||||||
(x', y', z')
|
|
||||||
$$
|
|
||||||
|
|
||||||
## 2. Rotationsmatrix um die x-Achse
|
|
||||||
|
|
||||||
Wenn wir einen Punkt
|
|
||||||
|
|
||||||
$$
|
|
||||||
\mathbf{v} = \begin{pmatrix} x \\ y \\ z \end{pmatrix}
|
|
||||||
$$
|
|
||||||
|
|
||||||
um die x-Achse um einen Winkel $\theta$ drehen wollen, benutzen wir die Rotationsmatrix:
|
|
||||||
|
|
||||||
$$
|
|
||||||
R_x(\theta) =
|
|
||||||
\begin{pmatrix}
|
\begin{pmatrix}
|
||||||
1 & 0 & 0 \\
|
x \\
|
||||||
0 & \cos\theta & -\sin\theta \\
|
y \\
|
||||||
0 & \sin\theta & \cos\theta
|
z
|
||||||
\end{pmatrix}
|
\end{pmatrix}.
|
||||||
$$
|
|
||||||
|
|
||||||
**Hinweis:**
|
|
||||||
- Die x-Koordinate bleibt gleich, weil wir um die x-Achse drehen.
|
|
||||||
- y und z verändern sich je nach Winkel $\theta$.
|
|
||||||
|
|
||||||
## 3. Berechnung des neuen Punktes
|
|
||||||
|
|
||||||
Der neue Punkt $\mathbf{v}'$ nach der Drehung ist:
|
|
||||||
|
|
||||||
$$
|
$$
|
||||||
\mathbf{v}' = R_x(\theta) \mathbf{v} =
|
|
||||||
\begin{pmatrix}
|
Eine Drehung des Würfels im Raum kann mathematisch durch **Multiplikation mit einer Rotationsmatrix** beschrieben werden.
|
||||||
1 & 0 & 0 \\
|
|
||||||
0 & \cos\theta & -\sin\theta \\
|
---
|
||||||
0 & \sin\theta & \cos\theta
|
|
||||||
\end{pmatrix}
|
## 2. Rotationsmatrizen im 3D-Raum
|
||||||
\begin{pmatrix} x \\ y \\ z \end{pmatrix} =
|
|
||||||
|
Eine Rotationsmatrix beschreibt eine Drehung um eine bestimmte Achse. Dabei bleibt die Länge der Vektoren unverändert, ebenso die Winkel zwischen ihnen.
|
||||||
|
Es gibt drei elementare Rotationen: um die **x-Achse**, die **y-Achse** und die **z-Achse**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### a) Rotation um die x-Achse
|
||||||
|
|
||||||
|
$$
|
||||||
|
\mathbf{v}' = R_x(\theta)\mathbf{v} =
|
||||||
\begin{pmatrix}
|
\begin{pmatrix}
|
||||||
x \\
|
x \\
|
||||||
y \cos\theta - z \sin\theta \\
|
y \cos\theta - z \sin\theta \\
|
||||||
y \sin\theta + z \cos\theta
|
y \sin\theta + z \cos\theta
|
||||||
\end{pmatrix}
|
\end{pmatrix}
|
||||||
$$
|
|
||||||
|
|
||||||
## 4. Beispiel
|
|
||||||
|
|
||||||
Drehen wir den Punkt
|
|
||||||
|
|
||||||
$$
|
|
||||||
\mathbf{A} = (1,1,1)
|
|
||||||
$$
|
$$
|
||||||
|
|
||||||
um
|
Die x-Koordinate bleibt bei dieser Drehung unverändert. Der Punkt
|
||||||
|
|
||||||
$$
|
$$
|
||||||
\theta = 90^\circ = \frac{\pi}{2}
|
\mathbf{v}' = R_x(\theta)\mathbf{v} =
|
||||||
$$
|
|
||||||
|
|
||||||
Dann gilt:
|
|
||||||
|
|
||||||
$$
|
|
||||||
\cos \theta = 0, \quad \sin \theta = 1
|
|
||||||
$$
|
|
||||||
|
|
||||||
$$
|
|
||||||
\mathbf{A}' =
|
|
||||||
\begin{pmatrix}
|
\begin{pmatrix}
|
||||||
1 \\
|
x \\
|
||||||
1 \cdot 0 - 1 \cdot 1 \\
|
y \cos\theta - z \sin\theta \\
|
||||||
1 \cdot 1 + 1 \cdot 0
|
y \sin\theta + z \cos\theta
|
||||||
\end{pmatrix} =
|
\end{pmatrix}
|
||||||
|
|
||||||
|
$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### b) Rotation um die y-Achse
|
||||||
|
|
||||||
|
$$
|
||||||
|
R_y(\theta) =
|
||||||
\begin{pmatrix}
|
\begin{pmatrix}
|
||||||
1 \\ -1 \\ 1
|
\cos\theta & 0 & \sin\theta \\
|
||||||
|
0 & 1 & 0 \\
|
||||||
|
-\sin\theta & 0 & \cos\theta
|
||||||
\end{pmatrix}
|
\end{pmatrix}
|
||||||
$$
|
$$
|
||||||
|
|
||||||
## 5. Tabelle aller Punkte nach Rotation
|
Dabei bleibt die y-Koordinate gleich, x und z verändern sich.
|
||||||
|
|
||||||
$$
|
$$
|
||||||
\begin{array}{c|c}
|
\mathbf{v}' = R_y(\theta)\mathbf{v} =
|
||||||
\text{Originalpunkt} & \text{Punkt nach Rotation} \\
|
\begin{pmatrix}
|
||||||
\hline
|
x \cos\theta + z \sin\theta \\
|
||||||
A (1,1,1) & (1,-1,1) \\
|
y \\
|
||||||
B (1,1,-1) & (1,-1,-1) \\
|
- x \sin\theta + z \cos\theta
|
||||||
C (1,-1,1) & (1,-1,-1) \\
|
\end{pmatrix}
|
||||||
D (1,-1,-1) & (1,1,-1) \\
|
|
||||||
E (-1,1,1) & (-1,-1,1) \\
|
|
||||||
F (-1,1,-1) & (-1,-1,-1) \\
|
|
||||||
G (-1,-1,1) & (-1,1,1) \\
|
|
||||||
H (-1,-1,-1) & (-1,1,-1) \\
|
|
||||||
\end{array}
|
|
||||||
$$
|
$$
|
||||||
|
|
||||||
## Fazit
|
---
|
||||||
|
|
||||||
- x bleibt unverändert
|
### c) Rotation um die z-Achse
|
||||||
- y und z ändern sich je nach Winkel
|
|
||||||
- Rotationsmatrizen sind ein mächtiges Werkzeug, um Objekte im 3D-Raum zu bewegen
|
|
||||||
|
|
||||||
|
$$
|
||||||
|
R_z(\theta) =
|
||||||
|
\begin{pmatrix}
|
||||||
|
\cos\theta & -\sin\theta & 0 \\
|
||||||
|
\sin\theta & \cos\theta & 0 \\
|
||||||
|
0 & 0 & 1
|
||||||
|
\end{pmatrix}
|
||||||
|
$$
|
||||||
|
|
||||||
|
Hier bleibt z unverändert, während x und y rotieren.
|
||||||
|
|
||||||
|
$$
|
||||||
|
\mathbf{v}' = R_z(\theta)\mathbf{v} =
|
||||||
|
\begin{pmatrix}
|
||||||
|
x \cos\theta - y \sin\theta \\
|
||||||
|
x \sin\theta + y \cos\theta \\
|
||||||
|
z
|
||||||
|
\end{pmatrix}
|
||||||
|
$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Kombination mehrerer Rotationen
|
||||||
|
|
||||||
|
Oft wird ein Objekt nacheinander um mehrere Achsen gedreht.
|
||||||
|
Die Gesamtrotation ergibt sich durch **Multiplikation der einzelnen Rotationsmatrizen**.
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
$$
|
||||||
|
R_{\text{gesamt}} = R_x(\alpha) \cdot R_y(\beta) \cdot R_z(\gamma).
|
||||||
|
$$
|
||||||
|
Ein Punkt $v$ wird dann abgebildet auf:
|
||||||
|
$$
|
||||||
|
\mathbf{v}' = R_{\text{gesamt}}\mathbf{v}.
|
||||||
|
$$
|
||||||
|
|
||||||
|
Die Reihenfolge ist dabei wesentlich, da die Matrixmultiplikation **nicht kommutativ** ist:
|
||||||
|
$$
|
||||||
|
R_x R_y \neq R_y R_x.
|
||||||
|
$$
|
||||||
|
|
||||||
|
Das bedeutet: Zuerst um die x-Achse und danach um die y-Achse zu drehen führt zu einem anderen Ergebnis, als die Reihenfolge umzukehren.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Matrixmultiplikation
|
||||||
|
|
||||||
|
Die Multiplikation zweier Matrizen (A) und (B) (jeweils 3×3) ergibt eine neue Matrix (C = A \cdot B) mit den Einträgen:
|
||||||
|
$$
|
||||||
|
c_{ij} = a_{i1}b_{1j} + a_{i2}b_{2j} + a_{i3}b_{3j}.
|
||||||
|
$$
|
||||||
|
|
||||||
|
Allgemein gilt:
|
||||||
|
|
||||||
|
* Jede Zeile von (A) wird mit jeder Spalte von (B) multipliziert.
|
||||||
|
* Die Summe dieser Produkte ergibt das jeweilige Element von (C).
|
||||||
|
|
||||||
|
So kann man Schritt für Schritt die Gesamtrotationsmatrix berechnen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Beispiel für ($\theta = 45^\circ$)
|
||||||
|
|
||||||
|
Für den Winkel $\theta = 45^\circ = \frac{\pi}{4}$ gilt:
|
||||||
|
$$
|
||||||
|
\cos\theta = \sin\theta = \frac{\sqrt{2}}{2}.
|
||||||
|
$$
|
||||||
|
|
||||||
|
Damit lautet die Rotationsmatrix um die x-Achse:
|
||||||
|
$$
|
||||||
|
R_x(45^\circ) =
|
||||||
|
\begin{pmatrix}
|
||||||
|
1 & 0 & 0 \\
|
||||||
|
0 & \tfrac{\sqrt{2}}{2} & -\tfrac{\sqrt{2}}{2} \\
|
||||||
|
0 & \tfrac{\sqrt{2}}{2} & \tfrac{\sqrt{2}}{2}
|
||||||
|
\end{pmatrix}
|
||||||
|
$$
|
||||||
|
|
||||||
|
Wendet man diese Matrix auf den Punkt $\mathbf{A} = (1, 1, 1)$ an, ergibt sich:
|
||||||
|
$$
|
||||||
|
\begin{aligned}
|
||||||
|
x' &= 1, \\
|
||||||
|
y' &= 1 \cdot \tfrac{\sqrt{2}}{2} - 1 \cdot \tfrac{\sqrt{2}}{2} = 0, \\
|
||||||
|
z' &= 1 \cdot \tfrac{\sqrt{2}}{2} + 1 \cdot \tfrac{\sqrt{2}}{2} = \sqrt{2}.
|
||||||
|
\end{aligned}
|
||||||
|
|
||||||
|
$$
|
||||||
|
|
||||||
|
Der neue Punkt ist also:
|
||||||
|
$$
|
||||||
|
\mathbf{A}' = (1, 0, \sqrt{2}).
|
||||||
|
$$
|
||||||
|
Der Punkt wurde damit um die x-Achse um 45° gedreht.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Zusammenfassung
|
||||||
|
|
||||||
|
* Eine **Rotationsmatrix** beschreibt eine Drehung im Raum.
|
||||||
|
* Die Länge eines Vektors bleibt bei der Rotation unverändert.
|
||||||
|
* Es gibt drei Grundmatrizen: $R_x(\theta)$, $R_y(\theta)$ und $R_z(\theta)$.
|
||||||
|
* Durch **Multiplikation** kann man mehrere Drehungen kombinieren.
|
||||||
|
* Die Reihenfolge der Rotationen ist **nicht vertauschbar**.
|
||||||
|
* Bei $45^\circ$ erscheinen häufig die Werte $\frac{\sqrt{2}}{2}$ und $\frac{1}{2}$.
|
||||||
Reference in New Issue
Block a user