Schraffur + Schichtfugen als 0.02-mm-Haarlinien im einheitlichen Neutralschwarz

Schraffurlinien verlassen den screenPx-Sonderpfad und laufen wie jede
andere Linie durch die Papier-mm-Pipeline (glPlan, SVG, PDF): im Display
konstante Haarlinie (paperScaleForGl-Kehrwert von meet), im Print echte
0.02 mm - deckungsgleich mit den Schichtfugen in beiden Modi.

- POCHE_STROKE #2b3039 -> #1a1a1a: kein Blaustich mehr, gleicher
  Neutralton wie die Schraffur (Wände/Öffnungen/Decken/Treppen).
- Schichtfuge LAYER_LINE_MM 0.13 -> 0.02 (Haarlinie).
- Schraffur-Stift hatch-hair/hatch-dash 0.05 -> 0.02.
- Wand-Umriss Kategorie 20 lw 0.5 -> 0.35 (Standard-Aussenlinie war zu dick).
- SVG-Schraffur nutzt HAIRLINE_PX/printStrokeVb statt hatchStrokePx;
  PDF-Export echte mm statt widthScreen.
This commit is contained in:
2026-07-03 20:02:18 +02:00
parent 675c68de55
commit 658536029b
6 changed files with 68 additions and 54 deletions
+37 -19
View File
@@ -1699,7 +1699,13 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
>
<defs>
{hatched.map((h) => (
<HatchPattern key={h.patternId} id={h.patternId} hatch={h.hatch} />
<HatchPattern
key={h.patternId}
id={h.patternId}
hatch={h.hatch}
hairline={!!hairline}
paperScale={paperScale}
/>
))}
</defs>
{/* Zeichenblatt-Hintergrund: deckt den aktuellen Ausschnitt (viewBox)
@@ -2347,28 +2353,37 @@ function needsPattern(pattern: HatchRender["pattern"]): boolean {
);
}
/**
* Übersetzt eine Linienstärke (mm) in Bildschirm-Pixel für Musterlinien.
* Bei 0.13 mm ergibt sich ~1 px (entspricht der bisherigen Dämmungs-/
* Diagonal-Strichstärke), damit die Schraffuren wie zuvor aussehen.
*/
const hatchStrokePx = (weightMm: number): number =>
Math.max(0.6, weightMm * (1 / 0.13));
/** Strichmuster (mm) → SVG dasharray (px) oder undefined (durchgezogen). */
function dashArray(dash: number[] | null): string | undefined {
if (!dash || dash.length === 0) return undefined;
return dash.map((d) => d * (1 / 0.13)).join(" ");
}
/**
* Ein parametrisiertes Schraffur-<pattern>. Maßstab skaliert die Kachelgröße,
* Winkel dreht das Muster (patternTransform), Farbe/Linienstärke kommen aus dem
* aufgelösten Hatch/LineStyle.
* aufgelösten Hatch/LineStyle. Die Musterlinie ist ein GEWÖHNLICHER Papier-mm-
* Stift (wie jede andere Linie) — dieselbe Display-/Print-Logik wie
* `renderPrimitive`: Display = konstante Haarlinie (Bildschirm-px, via
* non-scaling-stroke), Print = echte, PEN_STEPS-gequantelte Papier-mm.
*/
function HatchPattern({ id, hatch }: { id: string; hatch: HatchRender }) {
const sw = hatchStrokePx(hatch.lineWeight);
const dashes = dashArray(hatch.dash);
function HatchPattern({
id,
hatch,
hairline,
paperScale,
}: {
id: string;
hatch: HatchRender;
hairline: boolean;
paperScale: number | null;
}) {
const print = !hairline && paperScale != null && paperScale > 0;
const sw = hairline
? HAIRLINE_PX
: print
? printStrokeVb(quantizePen(hatch.lineWeight), paperScale!)
: mmToPx(hatch.lineWeight);
const vfx = print ? undefined : ("non-scaling-stroke" as const);
const dashes = hatch.dash?.length
? hatch.dash
.map((mm) => (print ? printStrokeVb(mm, paperScale!) : mmToPx(mm)))
.join(" ")
: undefined;
if (hatch.pattern === "insulation") {
// Weiche Zickzack-/Wellenlinie (SIA-nah). Kachel 14×10 × Maßstab.
@@ -2394,6 +2409,7 @@ function HatchPattern({ id, hatch }: { id: string; hatch: HatchRender }) {
stroke={hatch.color}
strokeWidth={sw}
strokeDasharray={dashes}
vectorEffect={vfx}
/>
</pattern>
);
@@ -2418,6 +2434,7 @@ function HatchPattern({ id, hatch }: { id: string; hatch: HatchRender }) {
stroke={hatch.color}
strokeWidth={sw}
strokeDasharray={dashes}
vectorEffect={vfx}
/>
{hatch.pattern === "crosshatch" && (
<line
@@ -2428,6 +2445,7 @@ function HatchPattern({ id, hatch }: { id: string; hatch: HatchRender }) {
stroke={hatch.color}
strokeWidth={sw}
strokeDasharray={dashes}
vectorEffect={vfx}
/>
)}
</pattern>