From 1c03e35e843fc0f335f65f1b6b14d0285d091970 Mon Sep 17 00:00:00 2001 From: Karim Date: Sun, 5 Jul 2026 20:31:04 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Kreise/B=C3=B6gen=20im=20WebGL-Renderer?= =?UTF-8?q?=20sichtbar=20(drawingCircle/drawingArc=20tesselliert;=20Regres?= =?UTF-8?q?sion=20aus=2021d76bd)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plan/glPlan/glPlanCompile.ts | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/plan/glPlan/glPlanCompile.ts b/src/plan/glPlan/glPlanCompile.ts index af2cbd4..add8cce 100644 --- a/src/plan/glPlan/glPlanCompile.ts +++ b/src/plan/glPlan/glPlanCompile.ts @@ -476,6 +476,54 @@ export function compilePrimitivesToGpu( arcPts.push({ x: c.x + prim.r * Math.cos(t), y: c.y + prim.r * Math.sin(t) }); } strokePolyline(arcPts, false, color, strokeMm); + } else if (prim.kind === 'drawingCircle' || prim.kind === 'drawingArc') { + // 2D-Zeichnungs-Kreis/-Bogen (Kreis-/Bogen-Werkzeug ODER DXF-Import). Der + // SVG-Pfad zeichnet sie als glattes /; die WebGL-Ebene kennt + // kein Kreis-Primitiv → hier bildschirm-adaptiv tessellieren (wie 'arc'). + // Kreis = voller Umlauf (geschlossen, optional gefüllt), Bogen = a0..a1 (CCW, + // offen). OHNE diesen Zweig blieben gezeichnete Kreise/Bögen im GL unsichtbar. + const stroke = parseColor(prim.stroke) ?? [0.1, 0.1, 0.1, 1]; + const strokeMm = prim.weightMm || 0.18; + const c = prim.center; + const TAU = Math.PI * 2; + const a0 = prim.kind === 'drawingArc' ? prim.a0 : 0; + const sweep = + prim.kind === 'drawingArc' + ? ((prim.a1 - prim.a0) % TAU + TAU) % TAU || TAU + : TAU; + // Segmentzahl wie im 'arc'-Zweig: Sagitta < ~0.5 px (LOD über pxPerMeter). + let segs: number; + if (pxPerMeter > 0) { + const rPx = prim.r * pxPerMeter; + const theta = rPx > 0.5 ? 2 * Math.acos(1 - 0.5 / rPx) : Math.PI; + segs = Math.min(2048, Math.max(8, Math.ceil(sweep / theta))); + } else { + segs = Math.max(8, Math.ceil((sweep / (Math.PI / 2)) * 16)); + } + const pts: Vec2[] = []; + for (let i = 0; i <= segs; i++) { + const t = a0 + (sweep * i) / segs; + pts.push({ x: c.x + prim.r * Math.cos(t), y: c.y + prim.r * Math.sin(t) }); + } + // Vollton-Füllung nur beim geschlossenen Kreis (Bogen ist offen). + if (prim.kind === 'drawingCircle') { + const fill = parseColor(prim.fill); + if (fill) { + const ring = pts.slice(0, segs); // ohne den doppelten Schlusspunkt + const tris = triangulate(ring); + if (tris.length) { + const base = fillPos.length / 2; + for (const pt of ring) { + const s = toScreen(pt); + fillPos.push(s.x, s.y); + track(pt.x, pt.y); + } + for (const t of tris) fillIdx.push(base + t); + addFillBatch(tris.length, fill); + } + } + } + strokePolyline(pts, prim.kind === 'drawingCircle', stroke, strokeMm); } // Text: bleibt im SVG-Overlay (scharfe Schrift, DOM-Hit-Test). }