/** * core-measure – Built-in V2-Plugin (Task A4.5). * * measure: 2 Klicks → Distanz+Winkel-Anzeige im Status. KEIN Element-Commit * (Legacy-Verhalten getreu — Messung ist Information, keine Zeichnung). * Distanzformatierung via bestehendem formatDistance(unit, scaleFactor). */ import type { PluginV2, ToolExtensionV2, FullToolContext } from '../../types'; import { formatDistance, formatArea } from '../../../utils/format'; import { polygonArea } from '../../../tools/modification/geometry'; type MeasurePhase = 0 | 1; // 0=wartet auf Start, 1=wartet auf Ende let measureStart: import('../../../tools/modification/geometry').Pt | null = null; export const measureTool: ToolExtensionV2 = { manifest: { id: 'measure', label: 'Messen', icon: '\u2194', ribbonTab: 'view', tags: ['basic'], description: 'Distanz und Winkel zwischen zwei Punkten messen', }, optionsSchema: [], handlers: { down(e, ctx) { const c = ctx as FullToolContext; if (!measureStart) { measureStart = e.world; ctx.setStatus('Messung: Endpunkt klicken'); return; } // Zweiter Klick → anzeigen (Legacy-Ausgabeformat) const rawDist = Math.hypot(e.world.x - measureStart.x, e.world.y - measureStart.y); const angle = (Math.atan2(e.world.y - measureStart.y, e.world.x - measureStart.x) * 180) / Math.PI; const unit = (c.options.unit as string | undefined) ?? 'mm'; const scale = (c.options.scaleFactor as number | undefined) ?? 1; const distStr = formatDistance(rawDist, unit as never, scale); ctx.setStatus(`distance: ${distStr} angle: ${angle.toFixed(1)}\u00b0`); measureStart = null; }, cancel(ctx) { measureStart = null; ctx.setStatus('Messung abgebrochen'); }, }, }; /** V2-Plugin: Messwerkzeuge. */ // ───────────────────────────────────────────────────────────── // Task H5: measure-area — Polygon-Fläche messen (Status-only). // Klick: Punkt hinzufügen; ENTER: committet Fläche ab 3 Punkten; // ESC/Rechtsklick: Abbruch. Kein Element-Commit (wie measure). // ───────────────────────────────────────────────────────────── let areaPts: Array<{ x: number; y: number }> = []; export const measureAreaTool: ToolExtensionV2 = { manifest: { id: 'measure-area', label: 'Fläche messen', icon: '\u25a9', ribbonTab: 'canvas', tags: ['basic'], description: 'Polygon-Fläche messen: Punkte klicken, ENTER schließt ab', }, optionsSchema: [ { key: 'unit', label: 'Einheit', type: 'select', options: [ { value: 'mm', label: 'mm' }, { value: 'cm', label: 'cm' }, { value: 'm', label: 'm' }, ] }, { key: 'scaleFactor', label: 'Maßstab (Welt→mm)', type: 'number' }, ], handlers: { down(e, ctx) { areaPts.push({ x: e.world.x, y: e.world.y }); if (areaPts.length === 1) { ctx.setStatus(`Flächenmessung gestartet (1 Punkt) — weitere Punkte klicken, ENTER schließt ab`); } else if (areaPts.length >= 3) { const unit = (ctx.options.unit as string | undefined) ?? 'mm'; const scale = (ctx.options.scaleFactor as number | undefined) ?? 1; ctx.setStatus(`Fläche: ${formatArea(polygonArea(areaPts), unit as never, scale)} — weiter klicken oder ENTER`); } else { ctx.setStatus(`${areaPts.length} Punkte — mindestens 3 benötigt, weitere Punkte klicken`); } }, move(e, ctx) { if (areaPts.length < 2) return; const probe = [...areaPts, { x: e.world.x, y: e.world.y }]; if (probe.length < 3) return; const unit = (ctx.options.unit as string | undefined) ?? 'mm'; const scale = (ctx.options.scaleFactor as number | undefined) ?? 1; ctx.setStatus(`Fläche: ${formatArea(polygonArea(probe), unit as never, scale)}`); }, key(k, ctx) { if (k.key === 'Enter' || k.key === 'ENTER') { if (areaPts.length >= 3) { const unit = (ctx.options.unit as string | undefined) ?? 'mm'; const scale = (ctx.options.scaleFactor as number | undefined) ?? 1; ctx.setStatus(`Flächenmessung: ${formatArea(polygonArea(areaPts), unit as never, scale)} (${areaPts.length} Punkte)`); areaPts = []; } else { ctx.setStatus(`Flächenmessung benötigt mindestens 3 Punkte (aktuell ${areaPts.length})`); } return true; // ENTER konsumiert } return false; }, cancel(ctx) { areaPts = []; ctx.setStatus('Flächenmessung abgebrochen'); }, }, }; export const coreMeasurePlugin: PluginV2 = { manifest: { id: 'core-measure', name: 'Messen (Kern)', version: '1.0.0', author: 'web-cad team', description: 'Abstandswinkel-Messung ohne Element-Erzeugung.', category: 'tools', enabledByDefault: true, }, tools: [measureTool, measureAreaTool], };