0cfddd8930
Neuer GPU-Renderer fuer den Grundriss (src/plan/glPlan/): Earcut-Tessellierung (konkav-faehig), gehrte Linienzuege (Miter), echte Papier-mm-Strichbreiten im Massstab (repliziert den SVG-printStrokeVb-Pfad), Hybrid mit scharfem SVG-Text- Overlay. GPU ist der Standardpfad; der SVG-Renderer bleibt automatischer Fallback, falls WebGL2/Shader nicht verfuegbar sind. Imperativer Pan (rAF + CSS-transform) fuer fluessige Interaktion ohne React-Re-Render je Frame. Enthaelt zudem den bisher nicht committeten Arbeitsstand des Browser-BIM (Oeffnungen, Treppen, Raeume, Decken, DXF-Export, Materialbibliothek, Kontext- Import, Tauri-Compute-Boundary-PoC).
65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
// Join — verbindet die gewählten 2D-Zeichenelemente an koinzidenten Endpunkten zu
|
|
// Polylinien (geschlossen, wenn sich eine Kette schließt). Sofort-Befehl (kein
|
|
// Punkt-Picken): läuft direkt auf der bestehenden Mehrfachauswahl. So ist „Ctrl+J"
|
|
// und getipptes „join" EIN Pfad (§Task C).
|
|
//
|
|
// Wände werden nicht verbunden (2D-Editier-Operation); nicht-polyline Formen
|
|
// (circle/arc/text) reicht `joinDrawings` unverändert durch.
|
|
|
|
import { joinDrawings } from "../../editors/splitJoin";
|
|
import type { Drawing2D } from "../../model/types";
|
|
import type {
|
|
Command,
|
|
CommandContext,
|
|
CommandResult,
|
|
CommandSelection,
|
|
CommandState,
|
|
Project,
|
|
} from "../types";
|
|
|
|
/** Alle gewählten 2D-Element-IDs (Mehrfachauswahl mit Fallback aufs Einzelelement). */
|
|
function selectedDrawingIds(sel: CommandSelection): string[] {
|
|
if (sel.drawingIds && sel.drawingIds.length) return sel.drawingIds;
|
|
return sel.drawingId ? [sel.drawingId] : [];
|
|
}
|
|
|
|
/** Ersetzt die gewählten Quell-Drawings durch das Join-Ergebnis (immutabel). */
|
|
function applyJoin(project: Project, ids: string[]): Project {
|
|
const idSet = new Set(ids);
|
|
const srcs = project.drawings2d.filter((d) => idSet.has(d.id));
|
|
if (srcs.length < 2) return project; // <2 → nichts zu verbinden
|
|
const joined: Drawing2D[] = joinDrawings(srcs);
|
|
const rest = project.drawings2d.filter((d) => !idSet.has(d.id));
|
|
return { ...project, drawings2d: [...rest, ...joined] };
|
|
}
|
|
|
|
interface JoinState extends CommandState {
|
|
phase: "done";
|
|
}
|
|
|
|
const done = (): [CommandState, CommandResult] => [
|
|
{ phase: "done", lastPoint: null } as JoinState,
|
|
{ draft: null, done: true },
|
|
];
|
|
|
|
export const joinCommand: Command = {
|
|
name: "join",
|
|
labelKey: "edit.join.label",
|
|
prompt: () => "cmd.join.prompt",
|
|
accepts: () => [],
|
|
options: () => [],
|
|
init: (): JoinState => ({ phase: "done", lastPoint: null }),
|
|
|
|
// Sofort auf der Auswahl ausführen (kein Pick nötig).
|
|
autoRun: (ctx: CommandContext): CommandResult => {
|
|
const ids = selectedDrawingIds(ctx.selection);
|
|
if (ids.length < 2) return { draft: null, done: true };
|
|
return { draft: null, done: true, commit: (p) => applyJoin(p, ids) };
|
|
},
|
|
|
|
onInput: (): [CommandState, CommandResult] => done(),
|
|
onMove: (state): [CommandState, CommandResult] => [state, { draft: null }],
|
|
onConfirm: (): [CommandState, CommandResult] => done(),
|
|
onCancel: (): [CommandState, CommandResult] => done(),
|
|
};
|