SIA-Wandschraffuren: Beton-Kreuz, Backstein/Dämmung wandrelativ, hairline
- HatchStyle.relativeToWall: der Wandwinkel (aus wall.start/end) wird in addWallPoche und resolveWallSectionStyle auf hatch.angle addiert (Vorzeichen zur SVG-CW-Konvention passend), sodass die Schraffur der Wandachse folgt. - sampleProject: sia-concrete (crosshatch 45° absolut), sia-brick (diagonal wandrelativ), sia-insulation (diagonal 90° wandrelativ, solide Haarlinie); Komponenten Beton/Backstein/Dämmung darauf umgehängt. Dichte Muster (scale 0.5/0.5/0.45), hairline (Strichgewicht 0.05 → 0.6px-Boden). - Poché-Hinterlegung: mehrschichtige Wände (und einschichtige) weiss, solid schwarz (Fill + Schraffurfarbe), konsistent in SVG- und glPlan-Fill; Mono behält Schwarz für solid. Gilt auch für den Schnitt-Cut. - ResourceManager: Wandbezug-Schalter im Hatch-Manager. exportDxf: Dash- Splitting für gestrichelte Schraffuren.
This commit is contained in:
+44
-1
@@ -126,8 +126,13 @@ function emitPrimitive(
|
||||
p.hatch.pattern !== "none" &&
|
||||
p.hatch.pattern !== "solid"
|
||||
) {
|
||||
const cycle = dashCycleMeters(p.hatch.dash);
|
||||
for (const seg of hatchSegments(pts, p.hatch)) {
|
||||
dxf.addLine(LAYER_HATCH, seg.a, seg.b);
|
||||
if (cycle) {
|
||||
for (const d of dashSeg(seg, cycle)) dxf.addLine(LAYER_HATCH, d.a, d.b);
|
||||
} else {
|
||||
dxf.addLine(LAYER_HATCH, seg.a, seg.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -174,6 +179,44 @@ interface Seg {
|
||||
b: Vec2;
|
||||
}
|
||||
|
||||
// Strichmuster (`dash`, mm-Papier) → Zyklus in WELT-Metern. Gleiche Umrechnung
|
||||
// wie der Bildschirm/GL-Pfad: 1 mm ≙ (1/0.13) Kachel-Einheiten, 1 Einheit = 1/90 m.
|
||||
// `null` = durchgezogen (keine Zerlegung). Ungerade Musterlängen werden verdoppelt.
|
||||
const DASH_MM_TO_M = (1 / 0.13) * (1 / 90);
|
||||
function dashCycleMeters(dash: number[] | null): number[] | null {
|
||||
if (!dash || dash.length === 0) return null;
|
||||
const pat = dash.map((d) => Math.max(0, d) * DASH_MM_TO_M).filter((d) => d > 0);
|
||||
if (pat.length === 0) return null;
|
||||
return pat.length % 2 === 0 ? pat : pat.concat(pat);
|
||||
}
|
||||
|
||||
// Zerlegt EINE Schraffurlinie in ihre durchgezogenen Teilstücke gemäß `cycle`
|
||||
// ([an, aus, …], Meter). Die Phase startet je Linie neu — visuell identisch zum
|
||||
// SVG-`<pattern>`, das das Muster je Kachellinie zurücksetzt.
|
||||
function dashSeg(seg: Seg, cycle: number[]): Seg[] {
|
||||
const out: Seg[] = [];
|
||||
const len = Math.hypot(seg.b.x - seg.a.x, seg.b.y - seg.a.y);
|
||||
if (len < 1e-9) return out;
|
||||
const ux = (seg.b.x - seg.a.x) / len;
|
||||
const uy = (seg.b.y - seg.a.y) / len;
|
||||
let pos = 0;
|
||||
let idx = 0;
|
||||
let on = true;
|
||||
while (pos < len - 1e-9) {
|
||||
const step = Math.min(cycle[idx % cycle.length], len - pos);
|
||||
if (on && step > 1e-9) {
|
||||
out.push({
|
||||
a: { x: seg.a.x + ux * pos, y: seg.a.y + uy * pos },
|
||||
b: { x: seg.a.x + ux * (pos + step), y: seg.a.y + uy * (pos + step) },
|
||||
});
|
||||
}
|
||||
pos += step;
|
||||
idx++;
|
||||
on = !on;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function hatchSegments(
|
||||
poly: Vec2[],
|
||||
hatch: Extract<Primitive, { kind: "polygon" }>["hatch"],
|
||||
|
||||
Reference in New Issue
Block a user