2D: Höhenkoten-Werkzeug + Masskette bleibt gerade + Punkt-Notation

Neues Werkzeug "Höhenkote" (SIA 400 B.5.4, Figur 18): Dreieck-Symbol +
Höhenwert an einem Punkt. Vier Varianten (OK/UK × fertig/roh) bestimmen
Dreieck-Richtung und Füllung, per Option umschaltbar. Die Norm ordnet
Zahlen UNTERHALB einer Masslinie explizit Höhenmassen zu — das war der
eigentliche Grund, warum ein separater Typ statt einer Bemassungs-Variante
nötig war.

Bemassungs-Korrektur: eine Masskette bleibt beim Zeichnen immer eine
GERADE Linie (Klicks ab dem dritten Punkt werden auf die durch Punkt 1/2
festgelegte Gerade projiziert), auch wenn die Bedienung wie eine Polylinie
funktioniert — vorher konnte man versehentlich einen Zickzack-Pfad
erzeugen.

Ausserdem: Masszahlen nutzen jetzt Punkt- statt Komma-Notation ("3.96"
statt "3,96") — die tatsächlich gezeichneten Beispiele in der Norm
(Figur 13/14/18) verwenden durchgängig den Punkt, nicht das Komma aus der
abstrakten B.5.2-Beispielliste.
This commit is contained in:
2026-08-22 02:32:11 +02:00
parent 4c7fc99eb8
commit 2dc57d01a5
21 changed files with 433 additions and 19 deletions
+23
View File
@@ -104,6 +104,29 @@ describe("dimensionCommand", () => {
expect(segs[1]).toMatchObject({ a: { x: 4, y: 0 }, b: { x: 10, y: 0 }, offset: 2 });
});
it("dritter Punkt ausserhalb der Geraden wird auf sie projiziert (keine Polylinie, immer gerade)", () => {
const p = project();
const ctx = makeCtx(p);
let [state] = dimensionCommand.onInput(
dimensionCommand.init(),
{ kind: "point", point: { x: 0, y: 0 } },
ctx,
);
// Richtung: entlang +x (y=0).
[state] = dimensionCommand.onInput(state, { kind: "point", point: { x: 4, y: 0 } }, ctx);
// Dritter Klick liegt bewusst NICHT auf der Geraden (y=3) → wird projiziert.
[state] = dimensionCommand.onInput(state, { kind: "point", point: { x: 10, y: 3 } }, ctx);
[state] = dimensionCommand.onConfirm(state, ctx);
const [, result] = dimensionCommand.onInput(state, { kind: "number", value: 1 }, ctx);
const next = result.commit!(p);
expect(next.drawings2d.length).toBe(2);
const second = next.drawings2d[1].geom;
if (second.shape === "dimension") {
expect(second.b.y).toBeCloseTo(0, 6); // auf die Gerade y=0 projiziert
expect(second.b.x).toBeCloseTo(10, 6); // x-Komponente bleibt (Projektion entlang x)
}
});
it("Zurück-Option entfernt den letzten Punkt", () => {
const p = project();
const ctx = makeCtx(p);