Cursor-HUD (VW-Stil) + weiches Winkel-Einrasten im Grundriss
Beim Zeichnen erscheint jetzt direkt am Cursor ein blau umrandetes Massband-Kästchen mit Länge/Winkel (L: 3.118m W: 60.000°, Winkel im Bereich (−180,180]) statt nur in der Befehlszeile. Zusätzlich rastet der Zugwinkel weich auf gängige Winkel (15°-Vielfache, Toleranz per Default 2.5°) ein, sobald kein Objekt-Snap greift — mit gelblichem Winkel-Badge und einer über den Cursor hinaus verlängerten, gestrichelten Führungslinie (Vectorworks-Vorbild). - tools/types.ts: ToolDraft.hud um length/angleDeg erweitert (text bleibt für Befehle ohne L/W-Paar), neuer segmentHud()-Helper. - tools/snapping.ts: neue reine Funktion snapCommonAngle() + Einbindung in computeSnap (Objekt-Snap > harter Ortho-Zwang > weiches Winkelraster > Raster). Neues SnapSettings-Feld commonAngles + commonAngleTolerance, neuer SnapKind "angle". - ui/StatusBar.tsx: Toggle + Toleranz-Eingabe in der Fang-Popover. - plan/PlanView.tsx: DraftHud- und AngleGuide-Overlay (screen-space, zoomunabhängige Größe); die Winkel-Info reitet auf draft.snap mit. - i18n: snap.commonAngles / snap.commonAngleTolerance (de/en). - snapping.test.ts: snapCommonAngle-Fälle (exakt/Toleranz/Bereich/ 15°-Raster/Projektion) + Objekt-Snap-Vorrang vor dem Winkelraster.
This commit is contained in:
+39
-4
@@ -33,16 +33,19 @@ export type SnapKind =
|
||||
| "onEdge"
|
||||
| "grid"
|
||||
| "ortho"
|
||||
| "extension";
|
||||
| "extension"
|
||||
| "angle";
|
||||
|
||||
export interface SnapResult {
|
||||
/** Gefangener Punkt (Meter). */
|
||||
point: Vec2;
|
||||
kind: SnapKind;
|
||||
/** Quell-Bezugspunkt (für Hilfslinien bei ortho/extension), optional. */
|
||||
/** Quell-Bezugspunkt (für Hilfslinien bei ortho/extension/angle), optional. */
|
||||
refA?: Vec2;
|
||||
/** Bildschirm-Distanz Cursor→Snap (px) — für die Auswahl des Besten. */
|
||||
distPx: number;
|
||||
/** Eingerasteter Winkel in Grad, Bereich (−180,180] — nur bei kind "angle". */
|
||||
angleDeg?: number;
|
||||
}
|
||||
|
||||
export interface SnapSettings {
|
||||
@@ -61,6 +64,10 @@ export interface SnapSettings {
|
||||
angleStep: number;
|
||||
/** Fangradius am Bildschirm in Pixeln. */
|
||||
tolerancePx: number;
|
||||
/** Weiches Einrasten auf gängige Winkel (15°-Vielfache), wenn kein Objekt-Snap greift. */
|
||||
commonAngles: boolean;
|
||||
/** Toleranz (Grad) für das weiche Winkel-Einrasten. */
|
||||
commonAngleTolerance: number;
|
||||
}
|
||||
|
||||
/** Default-Snap-Einstellungen (endpoint/midpoint/intersection/onEdge + grid). */
|
||||
@@ -76,6 +83,8 @@ export const DEFAULT_SNAP: SnapSettings = {
|
||||
ortho: false,
|
||||
angleStep: 90,
|
||||
tolerancePx: 12,
|
||||
commonAngles: true,
|
||||
commonAngleTolerance: 2.5,
|
||||
};
|
||||
|
||||
// ── Werkzeug-Schnittstelle ──────────────────────────────────────────────────
|
||||
@@ -125,8 +134,14 @@ export interface ToolDraft {
|
||||
vertices: Vec2[];
|
||||
/** Aktiver Snap (für den Bildschirm-Marker), optional. */
|
||||
snap?: SnapResult | null;
|
||||
/** Optionaler Maß-/Winkel-Text am Cursor (z. B. „3.20 m · 90°"). */
|
||||
hud?: { at: Vec2; text: string };
|
||||
/**
|
||||
* Maß-/Winkel-Anzeige am Cursor (Vectorworks-Stil: `L: 3.118m` + `W: 60.000°`
|
||||
* in einem blau umrandeten Kästchen). `length`/`angleDeg` speisen die VW-Box;
|
||||
* `text` bleibt für Befehle ohne Länge/Winkel-Paar (z. B. Radius, Fläche) als
|
||||
* einfaches Text-Label. Beide Formen sind additiv kombinierbar (text kann als
|
||||
* Zusatzzeile neben length/angleDeg stehen).
|
||||
*/
|
||||
hud?: { at: Vec2; text?: string; length?: number; angleDeg?: number };
|
||||
}
|
||||
|
||||
/** Was ein Werkzeug-Schritt nach außen meldet. */
|
||||
@@ -193,6 +208,26 @@ export interface ToolHandlers {
|
||||
draft: ToolDraft | null;
|
||||
}
|
||||
|
||||
// ── Cursor-HUD (VW-Stil L/W-Kästchen) ────────────────────────────────────────
|
||||
|
||||
/** Modell-Winkel atan2(dy,dx) in Grad — bereits im Bereich (−180,180] (VW-Konvention). */
|
||||
export function angleDegOf(from: Vec2, to: Vec2): number {
|
||||
return (Math.atan2(to.y - from.y, to.x - from.x) * 180) / Math.PI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Länge+Winkel-HUD für das aktive Segment `from → to` (VW-Stil `L: … W: …`).
|
||||
* Gemeinsamer Helper für alle Zeichenbefehle (line/polyline/wall/rect/…), damit
|
||||
* die Formatierung/Konvention EINMAL lebt statt in jedem Befehl neu.
|
||||
*/
|
||||
export function segmentHud(from: Vec2, to: Vec2): { at: Vec2; length: number; angleDeg: number } {
|
||||
return {
|
||||
at: to,
|
||||
length: Math.hypot(to.x - from.x, to.y - from.y),
|
||||
angleDeg: angleDegOf(from, to),
|
||||
};
|
||||
}
|
||||
|
||||
// ── ID-Vergabe ───────────────────────────────────────────────────────────────
|
||||
|
||||
let idCounter = 0;
|
||||
|
||||
Reference in New Issue
Block a user