Time to revisit SVG path to LDraw conversion?

Time to revisit SVG path to LDraw conversion?
#1
Yes, I'm thinking it's time!

Every pattern I create (which admittedly isn't that many yet) seems to involve passing through the SVG format at some point. But we're still missing a tool for converting SVG graphics directly to LDraw, and I know there have been a couple started already. (Img4Dat has planned SVG functionality, SvgToDat I believe handles basic primitives only, etc.)

My proposal is to start with the single task of converting SVG paths to vertices that can be imported, say, into LDPE at a reasonable resolution for mesh generation. And since SVG paths are really just a combination of cartesian coordinates (rel or abs) and Bezier control points, all that's really needed is a way to take the cubic Bezier math and make a polyline out of that—perhaps with an option between points evenly spaced, or according to curvature (so that tighter curves get more points). Best of all, that information is already stored in a nice, human-readable xml format within the svg file.

The use case for this arose when working on this part. I was able to lift those vectors directly from the official instruction booklet, put them into Inkscape, export a PNG and trace that manually in LDPE. But how much faster if I could have taken the paths themselves (or the xml data from inside the svg file) and drop them into a tool in LDPE, maybe adjust the precision a little bit, and instantly have the vertices I need to triangulate the pattern!

I'm thinking—in fact, I'm sure—that the math part of this has already been worked out many times over, and all that's missing is to code it in a way that's specific to LDraw. If we only focus on converting paths (which, again, is really just converting Bézier curves), then it think it becomes much easier to tackle than trying to incorporate the entire SVG spec into an LDraw tool, because a lot of that is probably stuff we can do more or less by hand.

So who's up for the challenge, and how can I help? I never learned to code, though I do understand programming languages generally. I just don't know a git from a commit from a pull request. ;-) And I'm not fluent in math, but I can figure out problems on an ad hoc basis, or at least look up the answers!
RE: Time to revisit SVG path to LDraw conversion?
#2
Speaking of looking up the answers, I read (some of) this page, and while it’s considerably more than a primer, it does contain lots of snippets of pseudo-code, including one to flatten a Bézier curve into linear segments, which is what we need a tool to do.

And for that matter, Inkscape should also be able to do this…
RE: Time to revisit SVG path to LDraw conversion?
#3
Although it is not a direct method, you can use Blender:

- File -> Import -> Scalable Vector Graphics (the resulting object is a path)

- Object Mode -> Object -> Convert -> Mesh (to get a triangulated shape)

- Object Mode -> Add Modifier -> Decimate (to reduce the number of faces when necessary)

- Edit Mode -> Face -> Tris to Quads (to convert some triangles to quadrilaterals)

- Export -> LDraw (you need to install the free extension ExportLdraw)
RE: Time to revisit SVG path to LDraw conversion?
#4
(2022-12-09, 21:18)Jose Alfonso Wrote: Although it is not a direct method, you can use Blender:

- File -> Import -> Scalable Vector Graphics (the resulting object is a path)

- Object Mode -> Object -> Convert -> Mesh (to get a triangulated shape)

- Object Mode -> Add Modifier -> Decimate (to reduce the number of faces when necessary)

- Edit Mode -> Face -> Tris to Quads (to convert some triangles to quadrilaterals)

- Export -> LDraw (you need to install the free extension ExportLdraw)

That's true, I always forget that you can go through Blender for some things.

The method I've devised for Inkscape is fiddly, but accurate. You have to:
1. Break your path apart to separate linear from Bezier segments;
2. Use "Add Nodes" on the Bezier segments ("Flatten Beziers" didn't give me the expected result) to get the appropriate number of vertices for LDraw precision;
3. Convert all segments between these nodes from curved to linear;
4. Re-assemble your path (you'll also want to render/commit any path effects, remove matrix transforms, etc.);
5. Run the "To Absolute" extension on your path so that the SVG outputs only X,Y pairs for the path nodes instead of relative translations;
6. Then from the XML editor you can select and copy/paste the code for the path ("d") element;
7. Now you have to do some find/replace text editing to convert the pasted code into, say, LDPE vertex lines, which you can then triangulate.

It's a lot of steps, but most of it is pretty rudimentary tasks that are probably easy to code. The only math-intensive step would be interpolating the additional nodes; otherwise, you can just strip control points from Bezier nodes, re-format the lines to LDraw spec, maybe even take the SVG transform tag and apply the matrix transform, if present.
RE: Time to revisit SVG path to LDraw conversion?
#5
What are the missing capabilities of svg2ldraw, since we want to start over again?

If you just want the points, you can convert the line types 3 and 4 to their corner points.

SVG2LDraw

I know people have previously been talking about "Delauney triangulations" and such, but that doesn't really make sense for the 4-sided polygons that LDraw allow for. So it must be something else that people yearn for - it is just not captured in the Issues and requests.
RE: Time to revisit SVG path to LDraw conversion?
#6
(2022-12-13, 6:39)Lasse Deleuran Wrote: What are the missing capabilities of svg2ldraw, since we want to start over again?

If you just want the points, you can convert the line types 3 and 4 to their corner points.

SVG2LDraw

I know people have previously been talking about "Delauney triangulations" and such, but that doesn't really make sense for the 4-sided polygons that LDraw allow for. So it must be something else that people yearn for - it is just not captured in the Issues and requests.

Is svg2ldraw the same as svg2dat? It could simply be that I had forgotten there were two different utilities out there. But now I am remembering that I once tried to use svg2ldraw and couldn't get past uploading the source file.

Trying again just now, I have some better luck, and I can offer at least some thoughts/observations:
• As has been said before, the triangulation seems very non-intuitive: lots of spidery mesh with many very thin triangles, for example. There are also many extra vertices added, often at seemingly arbitrary places.
• Because of this, it wouldn't be as simple as converting 3 and 4 lines to corner points, because you'd also have to clean up the extra ones.
• So, I do think it would be good to return only the nodes from the svg file itself: endpoints of straight segments, and any nodes added to Bezier segments. Generating the mesh could be a user-selected option.
• Perhaps a more interactive way to adjust the interpolation of Bezier points? Would it be trivial to implement a slider? I'm also not quite sure what "points per 100 pixels" means in relation to LDraw—I would be thinking more in terms of either maximum angle between segments, or approximating the 16/48-sided resolution of curved LDraw geometries.
• The program does not seem to recognize inner rings of an svg path (for example, it renders the letter 'o' as a solid circle, not a hollow ring).

Can the program only handle whole files, or would I be able to copy the SVG code of a single element in Inkscape and work with that alone?

Here is a file I used for testing (change .txt to .svg) so you can see what I mean. In this file, most of the letter paths have already been hand-simplified in Inkscape, but any letters that are repeated have not (e, a, i, r, G). I used a setting of 200 to simplify the curves before I approached what I'd consider an acceptable resolution, which feels like a lot.

Attached Files
RE: Time to revisit SVG path to LDraw conversion?
#7
SVG has been added as an allowed attachment type.
RE: Time to revisit SVG path to LDraw conversion?
#8
(2022-12-14, 4:21)N. W. Perry Wrote: Is svg2ldraw the same as svg2dat? It could simply be that I had forgotten there were two different utilities out there. But now I am remembering that I once tried to use svg2ldraw and couldn't get past uploading the source file.

Trying again just now, I have some better luck, and I can offer at least some thoughts/observations:
• As has been said before, the triangulation seems very non-intuitive: lots of spidery mesh with many very thin triangles, for example. There are also many extra vertices added, often at seemingly arbitrary places.
• Because of this, it wouldn't be as simple as converting 3 and 4 lines to corner points, because you'd also have to clean up the extra ones.
• So, I do think it would be good to return only the nodes from the svg file itself: endpoints of straight segments, and any nodes added to Bezier segments. Generating the mesh could be a user-selected option.
• Perhaps a more interactive way to adjust the interpolation of Bezier points? Would it be trivial to implement a slider? I'm also not quite sure what "points per 100 pixels" means in relation to LDraw—I would be thinking more in terms of either maximum angle between segments, or approximating the 16/48-sided resolution of curved LDraw geometries.
• The program does not seem to recognize inner rings of an svg path (for example, it renders the letter 'o' as a solid circle, not a hollow ring).

Can the program only handle whole files, or would I be able to copy the SVG code of a single element in Inkscape and work with that alone?

Here is a file I used for testing (change .txt to .svg) so you can see what I mean. In this file, most of the letter paths have already been hand-simplified in Inkscape, but any letters that are repeated have not (e, a, i, r, G). I used a setting of 200 to simplify the curves before I approached what I'd consider an acceptable resolution, which feels like a lot.
First. It seems like my hosting provider is having trouble with the redirect. While I try to get through their support, svg2ldraw has been made available here (more reliable link for now)

It seems like you ran into This issue back in 2019. It is a shame I was not made aware of it in 2019 - then I could have prioritised getting scientific notation in path commands to work back then.

- There is no triangulation. The decomposition consists of convex polygons. The convex polygons are then split up into mainly quads, and then possibly a single triangle to complete the split of a polygon. If a polygon has many points right next to each other, then thin quads will naturally occur. The only way to avoiding that would be to introduce Steiner points. Is this desired?

- There should be no "extra" vertices added. The LDraw file format consists of simple straight-line primitives, whereas the standard SVG standard contains arches, circles and other non-straight-line objects. The software attempts to approximate these non-straight-line objects using straight lines.

- Having a toggle for no "mesh" could be added. What would the output be, if only the points should be present? line type 2 with both points the same?

- "points per 100 pixels" is from svg, where svg works in its own scaling system. This is from before convertion to LDraw. Perhaps I should move the input field up to avoid confusion. Having a slider would be difficult to implement, as it would have to slide between 0.0001 and 0.0002 for some input files (such as those that need scientific notation for their points) to between 1000 and 1010 for those who have designed their SVG file to be big. But there are also SVG files with both big and small curves - but only one parameter to handle them all.
Going with the "angle change" approach might solve this issue. I would just have to make binary search on the curve conversion in order to get the right amount of points. Then a slider might also work, as the range is manageable.

- The "ring" issue is annoying. It appears that Inkscape generates paths within paths, and this should flip the colour. That feature is not yet recognized. To avoid this for now, the "holes" can be made in a separate colour in order to force Inkscape to output standard paths.

That is quite a list of change issues. Which one do you think is most important?

The code is in public domain. Anyone on the planet - and even off planet - is allowed to contribute to it. This should technically allow all issues to be solved extremely quickly.
RE: Time to revisit SVG path to LDraw conversion?
#9
(2022-12-14, 6:48)Lasse Deleuran Wrote: It seems like you ran into This issue back in 2019. It is a shame I was not made aware of it in 2019 - then I could have prioritised getting scientific notation in path commands to work back then.

It was later in 2020 when I ran into it, but true that I did not recognize it as being the same issue. But now it makes sense!

- There is no triangulation. The decomposition consists of convex polygons. The convex polygons are then split up into mainly quads, and then possibly a single triangle to complete the split of a polygon. If a polygon has many points right next to each other, then thin quads will naturally occur. The only way to avoiding that would be to introduce Steiner points. Is this desired?

The .dat file I get from my test file has an almost equal number of tris and quads (683 to 774). I'll attach the .dat so you can see what I mean. It does seem that adding points along the edge of the pattern would help, and yes, that is recommended by part reviewers.

Quote:- There should be no "extra" vertices added. The LDraw file format consists of simple straight-line primitives, whereas the standard SVG standard contains arches, circles and other non-straight-line objects. The software attempts to approximate these non-straight-line objects using straight lines.

Yeah, for some reason it did add a lot of extra vertices, both along what should otherwise be straight edges, and also in empty space between the paths. See:

Quote:- Having a toggle for no "mesh" could be added. What would the output be, if only the points should be present? line type 2 with both points the same?

I envisioned this as an LDPE extension, so I convert the path nodes to LDPE vertices (the 0 !LPE VERTEX meta). But type 2 lines could also be an option (regular lines though, not degenerate ones—basically just a wireframe of the paths).

Quote:- "points per 100 pixels" is from svg, where svg works in its own scaling system. This is from before convertion to LDraw. Perhaps I should move the input field up to avoid confusion. Having a slider would be difficult to implement, as it would have to slide between 0.0001 and 0.0002 for some input files (such as those that need scientific notation for their points) to between 1000 and 1010 for those who have designed their SVG file to be big. But there are also SVG files with both big and small curves - but only one parameter to handle them all.
Going with the "angle change" approach might solve this issue. I would just have to make binary search on the curve conversion in order to get the right amount of points. Then a slider might also work, as the range is manageable.

The more I think of it, the max angle approach seems to make the most sense, because the number of points needed depends on the steepness of the curve. Not every segment will need the same number of points, and so a raster-based method will inevitably provide too many points for very shallow curves, and/or too few for very sharp ones. This would also remove the need to choose a different precision per segment, and the 16/48-segment geometry of our circular prims doesn't really apply to Bézier curves (which cannot be circular anyway).

Quote:- The "ring" issue is annoying. It appears that Inkscape generates paths within paths, and this should flip the colour. That feature is not yet recognized. To avoid this for now, the "holes" can be made in a separate colour in order to force Inkscape to output standard paths.

Yes, in this case I believe the rings are subpaths of the larger letter. But you can also break apart the path in Inkscape, which would make the rings a truly separate path from the outline.

Quote:That is quite a list of change issues. Which one do you think is most important?

Thanks for the thoughtful reply. :-) Of course I was envisioning a more or less totally new tool, so this was not meant to be an actual request for all these changes! To me the most important would be converting path nodes to simple points (and/or type 2 lines), followed by maybe the angle-based interpolation method. If I have an accurate set of vertices, I don't really mind building the mesh myself, since I find that most mesh-generating tools require some manual refinement anyway, and it's often just as easy to re-draw whole sections.

Attached Files
RE: Time to revisit SVG path to LDraw conversion?
#10
Thanks for the screenshots. The points you show there seem to be erroneous. There should be no such "Steiner points" on line segments, unless they were added to remove T-Junktions.

The code is open source, so if a new tool should be made, then the existing code can be used for inspiration. The primary pieces of code to convert from SVG to LDraw is:
This files, which converts svg files to straight line primitives

These helper files:
Convert arc primitives
Convert Bezier curves

1) Fix the bugs with triangles and additional points, that should not be there.
2) Add point output for "0 !LPE VERTEX meta" as toggle
3) Change precision to "max angle" and allow the max angle to be configured.
4) Fix those InkScape overlapping path color conversions.
RE: Time to revisit SVG path to LDraw conversion?
#11
(2022-12-15, 7:45)Lasse Deleuran Wrote: Thanks for the screenshots. The points you show there seem to be erroneous. There should be no such "Steiner points" on line segments, unless they were added to remove T-Junktions.

The code is open source, so if a new tool should be made, then the existing code can be used for inspiration. The primary pieces of code to convert from SVG to LDraw is:
This files, which converts svg files to straight line primitives

These helper files:
Convert arc primitives
Convert Bezier curves

1) Fix the bugs with triangles and additional points, that should not be there.
2) Add point output for "0 !LPE VERTEX meta" as toggle
3) Change precision to "max angle" and allow the max angle to be configured.
4) Fix those InkScape overlapping path color conversions.

Thank you, and I will look through those code files and see if I can learn a thing or two about how such things can be programmed.

Just for reference, and to write it out for myself, this is the basic logic that I'm applying to the process, along with which tool/agent could be responsible for each step. Svg2ldraw already does more than this, of course, and this isn't meant to change how that tool works, only to lay out the process for the limited task of converting SVG paths. There are doubtless steps that I'm missing!

Input cleanup
1. Make paths "true" - remove/render/apply any path effects, matrix transforms, etc. so that the SVG path represents the actual appearance of the pattern. (Done by user in Inkscape or other tool, but LDraw tool could generate warnings if these elements are found. Tool could also apply matrix transforms fairly easily.)
2. Make paths absolute - convert relative lineto or curveto commands into absolute coord pairs, and add starting coords to any h or v commands. (Done easily by Inkscape extension, but also possible by LDraw tool.)
3. Break paths apart - split subpaths to separate paths, and paths into individual segments. (If necessary??)
Curve removal
1. Interpolate additional points between curve endpoints, to get new endpoints for straight segments. (Done by LDraw tool according to user settings.)
2. Convert curves to lines - using the new endpoints, strip all curveto commands to make Bezier segments into linear segments. (LDraw tool.)
Format conversion
1. Add missing 'z' coord to the absolute x/y pairs generated so far. (LDraw tool.)
2. Change syntax from SVG format to !LPE VERTEX meta commands or other appropriate LDraw format. (LDraw tool.)
RE: SVG...
#12
Please excuse my ignorance, but I presume that SVG is this:
https://en.wikipedia.org/wiki/SVG

Thanks,
Franklin
RE: SVG...
#13
(2022-12-15, 14:53)Franklin W. Cain Wrote: Please excuse my ignorance, but I presume that SVG is this:
https://en.wikipedia.org/wiki/SVG

You are correct.
RE: Time to revisit SVG path to LDraw conversion?
#14
Hey N. W. Perry,

in the current version, my test with your file in Img4Dat creates the following result (after I changed the height and the width inside the SVG).

But I think it is too detailed.

There are no colors respected and there are no intersections between paths - so it is easy...

Rolf

Attached Files
RE: Time to revisit SVG path to LDraw conversion?
#15
(2022-12-22, 14:21)Rolf Osterthun Wrote: Hey N. W. Perry,

in the current version, my test with your file in Img4Dat creates the following result (after I changed the height and the width inside the SVG).

Does Img4Dat import SVG now? (Or is this your own development version?)
RE: Time to revisit SVG path to LDraw conversion?
#16
(2022-12-23, 3:35)N. W. Perry Wrote: Does Img4Dat import SVG now? (Or is this your own development version?)

Hey,

it is just my development version. Still, there are too many things that are not supported and that guides to strange results very often. The development is idle, for quite some time now.

Rolf
RE: Time to revisit SVG path to LDraw conversion?
#17
(2022-12-22, 14:21)Rolf Osterthun Wrote: But I think it is too detailed.
A tad, yes. But now... that's a teaser !!!
RE: Time to revisit SVG path to LDraw conversion?
#18
(2022-12-23, 13:39)Philippe Hurbain Wrote: A tad, yes. But now... that's a teaser !!!

Well the source file is plenty detailed, so that's not unexpected. (This so that the letters can be sized up without losing too much resolution, if one should ever need them…)
« Next Oldest | Next Newest »

Forum Jump:

Users browsing this thread: 2 Guest(s)