DXF-Import: CIRCLE/ARC als echte glatte Kreis-/Bogen-Formen (statt tesselliertem Vieleck)
This commit is contained in:
@@ -471,6 +471,52 @@ describe("textsToDrawings", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseDxf — Kurven behalten echte Geometrie (curve)", () => {
|
||||
it("CIRCLE trägt curve {kind:circle}", () => {
|
||||
const c = onlyContour(dxf(circle(10, 20, 5, 4)));
|
||||
expect(c.curve?.kind).toBe("circle");
|
||||
expect(c.curve?.cx).toBeCloseTo(10, 9);
|
||||
expect(c.curve?.cy).toBeCloseTo(20, 9);
|
||||
expect(c.curve?.r).toBeCloseTo(4, 9);
|
||||
});
|
||||
|
||||
it("ARC trägt curve {kind:arc} mit Winkeln (Radiant)", () => {
|
||||
const c = onlyContour(dxf(arc(0, 0, 10, 0, 90)));
|
||||
expect(c.curve?.kind).toBe("arc");
|
||||
expect(c.curve?.r).toBeCloseTo(10, 9);
|
||||
expect(c.curve?.a0).toBeCloseTo(0, 9);
|
||||
expect(c.curve?.a1).toBeCloseTo(Math.PI / 2, 9);
|
||||
});
|
||||
});
|
||||
|
||||
describe("contoursToDrawings — Kurven → glatte Formen", () => {
|
||||
it("curve circle → {shape:\"circle\"}", () => {
|
||||
const set: ContourSet = {
|
||||
id: "s", type: "contourSet", name: "c",
|
||||
contours: [{ z: 0, closed: true, pts: [{ x: 0, y: 0 }], curve: { kind: "circle", cx: 1, cy: 2, r: 3, a0: 0, a1: Math.PI * 2 } }],
|
||||
};
|
||||
const [d] = contoursToDrawings([set], "lvl", "active", "C", (s) => s);
|
||||
expect(d.geom.shape).toBe("circle");
|
||||
if (d.geom.shape === "circle") {
|
||||
expect(d.geom.r).toBeCloseTo(3, 9);
|
||||
expect(d.geom.center.x).toBeCloseTo(1, 9);
|
||||
}
|
||||
});
|
||||
|
||||
it("curve arc → {shape:\"arc\"}", () => {
|
||||
const set: ContourSet = {
|
||||
id: "s", type: "contourSet", name: "c",
|
||||
contours: [{ z: 0, closed: false, pts: [{ x: 0, y: 0 }], curve: { kind: "arc", cx: 0, cy: 0, r: 5, a0: 0, a1: 1 } }],
|
||||
};
|
||||
const [d] = contoursToDrawings([set], "lvl", "active", "C", (s) => s);
|
||||
expect(d.geom.shape).toBe("arc");
|
||||
if (d.geom.shape === "arc") {
|
||||
expect(d.geom.r).toBeCloseTo(5, 9);
|
||||
expect(d.geom.a1).toBeCloseTo(1, 9);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("contoursToDrawings — HATCH-Füllung", () => {
|
||||
it("gefüllte Kontur → Drawing2D mit fillColor und polyline-Form", () => {
|
||||
const set: ContourSet = {
|
||||
|
||||
+14
-2
@@ -444,7 +444,13 @@ function arcContour(e: DxfEntity): Contour | null {
|
||||
const t = start + (sweep * i) / segs;
|
||||
pts.push({ x: cx + r * Math.cos(t), y: cy + r * Math.sin(t) });
|
||||
}
|
||||
return { z, pts, closed: false, layer: e.layer };
|
||||
return {
|
||||
z,
|
||||
pts,
|
||||
closed: false,
|
||||
layer: e.layer,
|
||||
curve: { kind: "arc", cx, cy, r, a0: start, a1: start + sweep },
|
||||
};
|
||||
}
|
||||
|
||||
/** CIRCLE → geschlossener Kreis-Linienzug (voller Umlauf, letzter Punkt weggelassen). */
|
||||
@@ -471,7 +477,13 @@ function circleContour(e: DxfEntity): Contour | null {
|
||||
const t = (Math.PI * 2 * i) / segs;
|
||||
pts.push({ x: cx + r * Math.cos(t), y: cy + r * Math.sin(t) });
|
||||
}
|
||||
return { z, pts, closed: true, layer: e.layer };
|
||||
return {
|
||||
z,
|
||||
pts,
|
||||
closed: true,
|
||||
layer: e.layer,
|
||||
curve: { kind: "circle", cx, cy, r, a0: 0, a1: Math.PI * 2 },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,6 +102,14 @@ export function textsToDrawings(
|
||||
|
||||
/** Eine Kontur → 2D-Geometrie (line bei 2 offenen Punkten, sonst polyline). */
|
||||
function contourGeom(contour: Contour): Drawing2DGeom | null {
|
||||
// Echte Kurve (CIRCLE/ARC) → GLATTE Kreis-/Bogen-Form statt tesselliertem Vieleck.
|
||||
const c = contour.curve;
|
||||
if (c) {
|
||||
if (c.kind === "circle") {
|
||||
return { shape: "circle", center: { x: c.cx, y: c.cy }, r: c.r };
|
||||
}
|
||||
return { shape: "arc", center: { x: c.cx, y: c.cy }, r: c.r, a0: c.a0, a1: c.a1 };
|
||||
}
|
||||
const pts = contour.pts;
|
||||
if (pts.length < 2) return null;
|
||||
if (pts.length === 2 && !contour.closed) {
|
||||
|
||||
Reference in New Issue
Block a user