Customers and design tools hand over SVGs, and getting them in meant a trip through another CAD tool. CadImporter now reads them like any other drawing, and plates, programs and converter entities can be written out. An SVG's numbers are not drawing units, so import converts to the nest's units and never guesses: only an absolute width or height counts as a stated size, since px means 1/96 in to browsers but 1/72 in to Illustrator. Without one the desktop asks, showing the size each choice gives, and headless callers must pass the scale or the import fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.2 KiB
SVG import and export
OpenNest.IO.Svg reads and writes SVG alongside DXF and DWG. Everything goes through CadImporter, so an SVG drawing behaves like any other import after loading. .svg is not in DrawingFileIndex: BOM imports still look for DXF and DWG only.
Scale
A DXF's numbers are taken as drawing units. An SVG's are not, so import converts to CadImportOptions.DrawingUnits (the nest's units in the desktop app) and never guesses.
The root element states a real-world size only when width or height uses an absolute unit: in, cm, mm, Q, pt or pc. Then:
- With a
viewBox, inches per user unit is the page size over the view box size. Mismatched aspect ratios fit uniformly, as browsers do, unlesspreserveAspectRatiostarts withnone. - Without one, a user unit is a CSS pixel, 1/96 inch.
Everything else does not count: a missing size, percentages and px or bare numbers. px is excluded on purpose, because a CSS pixel is 1/96 inch but Illustrator writes px at 72 per inch.
With no stated size, CadImportOptions.SvgUserUnitsPerInch supplies the scale, and without it the import throws InvalidDataException. A stated size always wins over that option. The desktop app asks with SvgScaleForm, which shows the size each choice produces; the console takes --svg-units-per-inch (--cad-units mm sets the drawing units) and MCP's import_dxf takes svgUnitsPerInch.
What import reads
Import takes path centerlines: path, rect (with rounded corners), circle, ellipse, line, polyline, polygon, g and use. Stroke widths and fills are ignored. Transforms are applied before an entity type is chosen, so a circle under a non-uniform scale becomes an ellipse.
- SVG's Y axis points down, so import negates Y. The view box origin is not subtracted, which keeps OpenNest's own exports at their original coordinates.
- Circular arcs stay arcs. Ellipses go through
EllipseConverter, and Bézier curves are sampled and fitted bySplineConverter, both within 0.001 in or 0.025 mm. - Malformed path data fails the import instead of importing part of a shape.
- Elements with
displaynone orvisibilityhidden or collapse are skipped, as are definition elements such asdefsandclipPath.<style>sheets are not read, so CSS-class hiding is not honored. - Text, images, nested
svg,useof asymbol, and shapes sized in percentages are skipped and listed inCadImportResult.Warnings. - Layers come from
data-layer, an Inkscape layer label, or theidof a top-level group (Illustrator).BEND,ETCH,SCRIBE,RAPIDandPLATEare dropped, so an exported plate reads back as its parts. - The file's DTD may parse, because older Illustrator files declare namespaces in one, but external fetches are off and entity expansion is capped.
- There is no bend detection: it reads a CAD document, which an SVG does not have.
What export writes
ExportProgram, ExportPlate and ExportEntities write one <g data-layer> per layer. width and height are in the given units and match the viewBox, so one user unit is one drawing unit and the file needs no scale prompt. Arcs stay A commands. The plate outline and edge spacing go on PLATE. Plate export leaves out the rapids DXF draws between parts.