# Exporting 3D to SVG

**URL:** <https://discourse.processing.org/t/exporting-3d-to-svg/25102>\
**Category:** Processing.py\
**Created:** [November 1, 2020, 8:13am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102 "2020-11-01T08:13:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![slashwreck](https://avatars.discourse-cdn.com/v4/letter/s/90db22/32.png) [@slashwreck](https://discourse.processing.org/u/slashwreck)\
**Post date:** [November 1, 2020, 8:13am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/1 "2020-11-01T08:13:05Z")

</div>

I have some code snippets that allow me to export normal 2d drawings to svg output. Today I made a simple 3d drawing. I want to flatten and export it to an svg. I tried using my 2d boilerplate but it doesn’t work.

What happens is that it ouputs an svg with multiple layers, as expected, but all the svgs are empty. I’m guessing this is because I’m in 3D not 2D.

```auto
#https://py.processing.org/tutorials/transform2d/
#https://py.processing.org/tutorials/p3d/

add_library('svg')
from xml.etree import ElementTree
OUTPUT_FN = '.\\combined.svg'

CANVAS = (1000,1000)
CUBE_COUNT = 5
SCALING = 1.5
ROTATE_X, ROTATE_Y, ROTATE_Z = (-PI/11, PI/8, 0)
BOX_SIZE = 30

def settings():
    pass
    
def setup():
    noLoop()
    global x,y,z
    size(CANVAS[0],CANVAS[1],P3D)
    x=width/2
    y=height/2
    z = 0
    
def draw():
    
    noFill()
    translate(x,y,z)
    rotateX(ROTATE_X)
    rotateY(ROTATE_Y)
    rotateZ(ROTATE_Z)

    svgs = []
    for n in range(CUBE_COUNT):
        fn = "{0}_box.svg".format(n)
        svgs.append(fn)
        beginRecord(SVG,fn)
        box(BOX_SIZE)
        scale(2,2,2)    
        endRecord()

    # create an empty combined.svg file
    beginRecord(SVG, OUTPUT_FN); endRecord()
    ElementTree.register_namespace('', 'http://www.w3.org/2000/svg')
    tree = ElementTree.parse(OUTPUT_FN)
    combined = tree.getroot()

    # add the (circles/squares) svgs to the combined.svg file
    for svg in svgs:
        file = ElementTree.parse(svg).getroot()
        group = ElementTree.SubElement(combined, 'g')
        group.set('id', svg)
        group.set('inkscape:groupmode', 'layer')
        group.set('inkscape:label', svg)
        for child in file.getchildren():
            group.append(child)
    
    # save the changes to the combined.svg file
    tree.write(OUTPUT_FN)
    
    print("done")

```

You can see the output svg is just an empty container of layers:

`<svg xmlns="http://www.w3.org/2000/svg" height="1000" style="fill-opacity:1; color-rendering:auto; color-interpolation:auto; text-rendering:auto; stroke:black; stroke-linecap:square; stroke-miterlimit:10; shape-rendering:auto; stroke-opacity:1; fill:black; stroke-dasharray:none; font-weight:normal; stroke-width:1; font-family:'Dialog'; font-style:normal; stroke-linejoin:miter; font-size:12px; stroke-dashoffset:0; image-rendering:auto;" width="1000"><defs id="genericDefs" /><g /><g id="0_box.svg" inkscape:groupmode="layer" inkscape:label="0_box.svg"><defs id="genericDefs" /><g /></g><g id="1_box.svg" inkscape:groupmode="layer" inkscape:label="1_box.svg"><defs id="genericDefs" /><g /></g><g id="2_box.svg" inkscape:groupmode="layer" inkscape:label="2_box.svg"><defs id="genericDefs" /><g /></g><g id="3_box.svg" inkscape:groupmode="layer" inkscape:label="3_box.svg"><defs id="genericDefs" /><g /></g><g id="4_box.svg" inkscape:groupmode="layer" inkscape:label="4_box.svg"><defs id="genericDefs" /><g /></g></svg>`

---

<div class="post-metadata">

**Author:** ![tabreturn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tabreturn/32/3697_2.png) [@tabreturn](https://discourse.processing.org/u/tabreturn)\
**Post date:** [November 1, 2020, 8:39am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/2 "2020-11-01T08:39:12Z")

</div>

Have you tried this approach?

```auto
size(500, 500, P3D);
beginRaw(SVG, 'output.svg')
translate(250, 250)
rotateZ(0.2)
rotateY(0.2)
box(100)
endRaw()

```

Note, however, that everything is constructed from triangles.

 ![Screenshot from 2020-11-01 21-46-58](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b2f2552596087c117058b1614805e56f82a78eb4.png)

---

<div class="post-metadata">

**Author:** ![slashwreck](https://avatars.discourse-cdn.com/v4/letter/s/90db22/32.png) [@slashwreck](https://discourse.processing.org/u/slashwreck)\
**Post date:** [November 1, 2020, 9:12am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/3 "2020-11-01T09:12:45Z")

</div>

> [@tabreturn](#):
>
> ```auto
> size(500, 500, P3D);
> beginRaw(SVG, 'output.svg')
> translate(250, 250)
> rotateZ(0.2)
> rotateY(0.2)
> box(100)
> endRaw()
> 
> ```

![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f7bc86cdc877c461b3ef99aec5addc8d22b1fd9e.png)

yeah, turns out it worked ok. Not sure why your cube shows triangles forming the sides – as neither my Processing output, nor the svg (in inkscape) shows them (fortunately).

Thanks for the hint on `beginRaw()` – now I need to figure out if I can separate the [different cubes into the different layers](https://discourse.processing.org/t/exporting-3d-to-svg/25102) like I do when I use `beginRecord()`.

---

<div class="post-metadata">

**Author:** ![tabreturn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tabreturn/32/3697_2.png) [@tabreturn](https://discourse.processing.org/u/tabreturn)\
**Post date:** [November 1, 2020, 9:27am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/4 "2020-11-01T09:27:07Z")

</div>

The triangles are invisible. In Inkscape, select **View \> Display Mode \> Outline** and you’ll see them.

I suspect that you intend plotting this? In which case, the triangles will show up in the plot. If that’s an issue, you could remove (programmatically) all of the paths in the SVG that have no stroke – i.e. anything with an attribute of `style="stroke:none;"`

---

<div class="post-metadata">

**Author:** ![slashwreck](https://avatars.discourse-cdn.com/v4/letter/s/90db22/32.png) [@slashwreck](https://discourse.processing.org/u/slashwreck)\
**Post date:** [November 1, 2020, 9:30am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/5 "2020-11-01T09:30:39Z")

</div>

Huh, strange. Even in Inkscape 1.0 when I goto View::Display\_mode::Outline, I never see the triangle ‘cross-members’. (which is a good thing!)

And when I print to my AxiDraw plotter, I also just get the edges of the wireframe (the result I want) and no triangle cross-members.

---

<div class="post-metadata">

**Author:** ![tabreturn](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tabreturn/32/3697_2.png) [@tabreturn](https://discourse.processing.org/u/tabreturn)\
**Post date:** [November 1, 2020, 9:51am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/7 "2020-11-01T09:51:44Z")

</div>

Interesting! Could you tell me if the SVG source code contains any elements with an attribute of `style="stroke:none;"`? I’m wondering if this is a Processing- or Inkscape-related difference.

---

<div class="post-metadata">

**Author:** ![slashwreck](https://avatars.discourse-cdn.com/v4/letter/s/90db22/32.png) [@slashwreck](https://discourse.processing.org/u/slashwreck)\
**Post date:** [November 1, 2020, 11:45am UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/8 "2020-11-01T11:45:16Z")

</div>

[Here is the svg output of my program.](https://pastebin.com/TMeQUdq3)

For reference, Inkscape is version 1.0 (4035a4fb49, 2020-05-01) and Processing 3.5.4 with Python Mode 3063.

This is the code I used:

> #[2D Transformations \ Tutorials](https://py.processing.org/tutorials/transform2d/)  
> #[P3D \ Tutorials](https://py.processing.org/tutorials/p3d/)
> 
> add\_library(‘svg’)  
> from xml.etree import ElementTree  
> OUTPUT\_FN = ‘.\combined.svg’
> 
> CANVAS = (1000,1000)  
> CUBE\_COUNT = 5  
> SCALING = 1.5  
> ROTATE\_X, ROTATE\_Y, ROTATE\_Z = (-PI/11, PI/8, 0)  
> BOX\_SIZE = 30
> 
> def settings():  
> pass
> 
> def setup():  
> noLoop()  
> global x,y,z  
> size(CANVAS[0],CANVAS[1],P3D)  
> x=width/2  
> y=height/2  
> z = 0
> 
> def draw():
> 
> ```
> noFill()
> translate(x,y,z)
> rotateX(ROTATE_X)
> rotateY(ROTATE_Y)
> rotateZ(ROTATE_Z)
> 
> svgs = []
> for n in range(CUBE_COUNT):
> fn = "{0}_box.svg".format(n)
> svgs.append(fn)
> #beginRecord(SVG,fn)
> beginRaw(SVG,fn)
> box(BOX_SIZE)
> scale(2,2,2)    
> #endRecord()
> endRaw()
>     
> # create an empty combined.svg file
> beginRecord(SVG, OUTPUT_FN); endRecord()
> ElementTree.register_namespace('', 'http://www.w3.org/2000/svg')
> tree = ElementTree.parse(OUTPUT_FN)
> combined = tree.getroot()
> 
> # add the (circles/squares) svgs to the combined.svg file
> for svg in svgs:
> file = ElementTree.parse(svg).getroot()
> group = ElementTree.SubElement(combined, 'g')
> group.set('id', svg)
> group.set('inkscape:groupmode', 'layer')
> group.set('inkscape:label', svg)
> for child in file.getchildren():
> group.append(child)
> 
> # save the changes to the combined.svg file
> tree.write(OUTPUT_FN)
> 
> print("done")
> 
> ```

---

<div class="post-metadata">

**Author:** ![Abby339](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@Abby339](https://discourse.processing.org/u/Abby339)\
**Post date:** [November 15, 2020, 8:44pm UTC](https://discourse.processing.org/t/exporting-3d-to-svg/25102/9 "2020-11-15T20:44:56Z")

</div>

See here: [https://stylecampaign.com/blog/2014/03/3d-to-svg/](https://stylecampaign.com/blog/2014/03/3d-to-svg/)
