microsoft / maker.js

📐⚙ 2D vector line drawing and shape modeling for CNC and laser cutters.
http://maker.js.org
Apache License 2.0
1.78k stars 275 forks source link

Nested SVG Paths not retained in model #608

Open Gautam2010 opened 2 months ago

Gautam2010 commented 2 months ago

I am providing an SVG path for the letter "O", which contains a hole defined by a child path. However, when I import this into a model, the child path becomes independent rather than being treated as part of parent shape.

Is there a way to ensure the child path is preserved as part of the parent shape in model, maintaining the hole inside the "O".

M893.245 123c56.018 0 92.769 20.454 92.769 66.03 0 38.683-27.339 92.487-115.407 92.487-52.658 0-95.235-20.239-95.235-70.703 0-48.239 39.662-87.814 117.873-87.814z

M873.97 239.497c28.684 0 39.217-33.349 39.217-46.466 0-18.01-6.052-28.011-25.545-28.011-29.136 0-39.44 34.456-39.44 50.24 0 12.008 5.154 24.237 25.769 24.237z

image

let baseModel: IModel = {};
baseModel.models = {}
baseModel.models[1] = importer.fromSVGPathData(dAttribute1);
baseModel.models[2] = importer.fromSVGPathData(dAttribute2);

var chains = model.findChains(baseModel);

        let finalSvgPath = '';
        let childChainSvgPath = '';
        chains.forEach((c, i) => {
            c.contains?.forEach((childChain, j) => {
                childChainSvgPath += chainToSVGPathData(childChain, [0, 0]);
            })
            finalSvgPath += chainToSVGPathData(c, [0, 0]);
        });

finalSvgPath is showing child path is not filled.

image

M 930.3069047 126.665486 A 171.3493909 171.3493909 0 0 0 893.245 123 A 189.9507124 189.9507124 0 0 0 853.8853658 126.8501533 A 122.9083701 122.9083701 0 0 0 814.9254538 141.8095565 A 78.8907062 78.8907062 0 0 0 775.372 210.814 A 77.6758437 77.6758437 0 0 0 776.8771862 226.3974017 A 64.6903108 64.6903108 0 0 0 825.1852422 275.2828569 A 152.2802865 152.2802865 0 0 0 870.607 281.517 A 186.9097031 186.9097031 0 0 0 896.3458414 279.821761 A 133.422669 133.422669 0 0 0 929.0460636 271.2194733 A 96.6261223 96.6261223 0 0 0 958.8274331 252.2488427 A 86.3227394 86.3227394 0 0 0 981.7140419 215.9447436 A 88.9482543 88.9482543 0 0 0 983.8438592 208.1864803 A 87.0520074 87.0520074 0 0 0 986.014 189.03 A 80.3313126 80.3313126 0 0 0 985.8483987 183.8282157 A 55.5498344 55.5498344 0 0 0 962.0295567 139.8806639 A 87.747383 87.747383 0 0 0 930.3069047 126.665486 ZM 873.97 239.497 A 32.640317 32.640317 0 0 0 887.8967783 236.4953314 A 43.3357113 43.3357113 0 0 0 908.0831174 214.0872647 A 62.3413931 62.3413931 0 0 0 908.2715094 213.6591215 A 64.4620702 64.4620702 0 0 0 911.6778023 203.656544 A 54.3165033 54.3165033 0 0 0 912.9060712 197.1846618 A 34.2847 34.2847 0 0 0 913.1870001 193.031 A 51.863543 51.863543 0 0 0 912.1691112 182.0463138 A 21.3624797 21.3624797 0 0 0 906.5501516 170.9965396 A 19.8238906 19.8238906 0 0 0 897.1661876 166.0438197 A 39.5609778 39.5609778 0 0 0 887.8115023 165.0202531 A 56.6225618 56.6225618 0 0 0 887.642 165.0200001 A 32.1753963 32.1753963 0 0 0 872.8461686 168.4727174 A 45.575518 45.575518 0 0 0 852.390439 194.0052888 A 70.8973047 70.8973047 0 0 0 849.3351123 204.8119902 A 60.5394661 60.5394661 0 0 0 848.3143866 212.2391089 A 42.91346 42.91346 0 0 0 848.202 215.26 A 41.2631979 41.2631979 0 0 0 848.2069296 215.8996013 A 22.3263515 22.3263515 0 0 0 857.466221 235.4731981 A 24.1127872 24.1127872 0 0 0 865.6216118 238.6964171 A 40.3244021 40.3244021 0 0 0 873.971 239.497 Z

danmarshall commented 2 months ago

This is a fundamental concept, by design in Maker.js that paths are independent: https://maker.js.org/docs/basic-drawing/#Path%20independence%20and%20Chains . Closed geometries are "found" not defined.

You're using chainToSVGPathData, which is a low level function to handle one chain, but when you have nested closed geometries the SVG exporter does this work for you. You will need to decide how you want to handle the SVG Fill Rule - either even-odd or non-zero (the latter requires more compute).

Check the source code for the NonZero flag in the svg exporter: https://github.com/microsoft/maker.js/blob/master/packages/maker.js/src/core/svg.ts#L279

Gautam2010 commented 1 month ago

@danmarshall SVG exporter is designed to work with nested closed geometries, but I'm specifically using the low-level function chainToSVGPathDatabecause I want to manage individual shape paths.

My goal is to:

Retrieve individual shape paths while maintaining their parent-child relationships and process them for business case.

Combine these paths together to model and export through svg exporter.

Given this context, is there a method or approach in Maker.js that allows me to get the path data for individual shapes with parent child fill?

Gautam2010 commented 1 month ago

@danmarshall

Even though I have tried with exporter.toSvg() method, my svgResponse is still showing filled as same.

image

image