Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2d export #190

Merged
merged 8 commits into from
Mar 26, 2023
Merged

2d export #190

merged 8 commits into from
Mar 26, 2023

Conversation

jrmobley
Copy link
Contributor

I have refactored the SVG and DXF export into three classes. The Drawing class creates an XY planar projection of a shape and provides the hidden and visible edges. The ExportDXF and ExportSVG classes provide multi-layer export of XY planar shapes to DXF and SVG files respectively.

All b-splines are reduced to at most 3rd degree. B-Splines are converted to poly-bézier curves for SVG export. Conics other than circles and ellipses are exported as b-splines/béziers. Bézier curves are exported to DXF as b-splines. Otherwise edges are exported in their original form.

The interfaces of ExportDXF and ExportSVG are both modeled after features of DXF as exposed by the ezdxf library. I have attempted to make the SVG output match DXF output as closely as possible.

I took the liberty of making some biggish decisions in this PR, so I wanted to get it posted for discussion and feedback.

@codecov
Copy link

codecov bot commented Mar 24, 2023

Codecov Report

Patch coverage has no change and project coverage change: -7.73 ⚠️

Comparison is base (5bf490d) 92.01% compared to head (75b1da5) 84.29%.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #190      +/-   ##
==========================================
- Coverage   92.01%   84.29%   -7.73%     
==========================================
  Files          13       14       +1     
  Lines        4673     5101     +428     
==========================================
  Hits         4300     4300              
- Misses        373      801     +428     
Impacted Files Coverage Δ
src/build123d/exporters.py 0.00% <0.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@gumyr
Copy link
Owner

gumyr commented Mar 26, 2023

This is excellent work, a huge thank you. Please remove "draft" so it can be merged and we can play with it.

The user would do something like:

svg_file = ExportSVG(unit=Unit.MILLIMETER, line_weight=0.5)
svg_file.add_layer(name="template", line_weight=.., line_type=..)
svg_file.add_shape(template_edges, layer="template")
svg_file.add_layer(name="main", ...)
svg_file.add_shape(my_objects, layer="main")
svg_file.write(...)

?
Currently there is a simple cad_objects.export_svg(...) interface, it doesn't even seem worth keeping this.

@jdegenstein you've done a lot of SVG - what do you think?

@jrmobley
Copy link
Contributor Author

Ok, I'll mark this ready for review.

Here is one of my usage examples:

        svg = ExportSVG(margin=5, line_weight=0.13)
        svg.add_shape(dwg.visible_lines)
        svg.add_layer("hidden", color=ColorIndex.LIGHT_GRAY, line_weight=0.09, line_type=LineType.ISO_DASH_SPACE)
        svg.add_shape(dwg.hidden_lines, layer="hidden")
        svg.write("dev-drawing.svg")

Shapes added without a layer argument are added to the default layer. The default layer properties are supplied you construct the exporter.

Here is how I make a section for export. The exporter expects all topology to be in the XY plane.

with BuildPart() as x:
    Add(pcb)
    Section(m3_plane)
section: Compound = m3_plane.to_local_coords(x.part)

Regarding the cad_objects.export_svg(...) interfaces, you could ditch them or just re-implement them with the new exporters. I'm ambivalent about that one.

@jrmobley jrmobley marked this pull request as ready for review March 26, 2023 19:47
@gumyr gumyr merged commit 21dd7e2 into gumyr:dev Mar 26, 2023
@jdegenstein
Copy link
Collaborator

Looks very interesting! I haven't tried it yet, but I would like to create e.g. the build123d logo without using inkscape. I want to be able to control line width/color and fill color. Is this possible with the new changes?

@jrmobley
Copy link
Contributor Author

Looks very interesting! I haven't tried it yet, but I would like to create e.g. the build123d logo without using inkscape. I want to be able to control line width/color and fill color. Is this possible with the new changes?

I'm afraid it isn't really possible right now. With the Drawing in particular, I don't think the underlying OCCT hidden-line removal algorithm maintains or reconstructs any information about faces. So the output has no closed shapes to fill, it's just a line soup. Maybe there is a completely different algorithm available that would be more suitable? Research required.

For 2D sections, it is also currently processed as a line soup, but there does exist the possibility of traversing down the topology tree and organizing the output into fillable shapes. But as the implementation stands currently, no the user cannot get filled output.

Regarding per-line colors and filled output, @gumyr I know you mention this in issue 56, and I was thinking about implementation. The primary obstacle I see is that below the level of Compound in the topology tree, you have to rely upon OCCT to enumerate the child objects, and so you get OCCT objects without the b3d wrappers, so it seems like color assignments would be lost. AFAICT.

@jrmobley jrmobley deleted the 2d-export branch March 27, 2023 17:22
@gumyr
Copy link
Owner

gumyr commented Mar 27, 2023

@jrmobley by "you have to rely upon OCCT to enumerate the child objects" is this being done with OCCT methods or edges(). I ask because (in the algebra branch) I've made modifications such that edges() assigns a new topo_parent instance variable (this was done so the parent shape doesn't need to be provided in a fillet). Thus is would be easy to find a parent's color and use that.

@jrmobley
Copy link
Contributor Author

The exporters right now are using edges() so that topo_parent could enable some stuff. I was picturing a tree traversal like you do in show_topology() in order to keep the structure intact when exporting SVG, but maybe that is overkill?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants