File: openscad.py

package info (click to toggle)
ezdxf 1.4.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 104,528 kB
  • sloc: python: 182,341; makefile: 116; lisp: 20; ansic: 4
file content (85 lines) | stat: -rw-r--r-- 2,867 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Copyright (c) 2020-2022, Manfred Moitzi
# License: MIT License
import pathlib
import ezdxf
from ezdxf.render import forms
from ezdxf.addons import MengerSponge, openscad

CWD = pathlib.Path("~/Desktop/Outbox").expanduser()
if not CWD.exists():
    CWD = pathlib.Path(".")

# ------------------------------------------------------------------------------
# This example shows how to utilize OpenSCAD for construction tasks by ezdxf.
# Shows the usage of the 'meshex' add-on to export/import meshes to/from OpenSCAD.
#
# docs:
# openscad: https://ezdxf.mozman.at/docs/addons/openscad.html
# meshex: https://ezdxf.mozman.at/docs/addons/meshex.html
# ------------------------------------------------------------------------------

POLYHEDRON = str(CWD / "OpenSCAD_polyhedron.dxf")
POLYGON = str(CWD / "OpenSCAD_polygon.dxf")


def polygon(filename):
    doc = ezdxf.new()
    doc.layers.add("NORMALS", color=3)
    msp = doc.modelspace()
    exterior = list(forms.square(10, center=True))
    hole = list(forms.circle(16, 0.5))
    holes = [
        list(forms.translate(hole, (-3, 3))),
        list(forms.translate(hole, (3, 3))),
        list(forms.translate(hole, (-3, -3))),
        list(forms.translate(hole, (3, -3))),
    ]
    script = openscad.Script()
    script.add("linear_extrude(height = 1, convexity=10)")
    script.add_polygon(exterior, holes)
    result = openscad.run(script.get_string())
    print("Result has:")
    print(f"{len(result.vertices)} vertices")
    print(f"{len(result.faces)} faces")
    result.render_mesh(msp)
    doc.saveas(filename)
    print(f"exported DXF file: '{filename}'")


# IMPORTANT:
# OpenSCAD expects clockwise ordered face-vertices to create outward pointing
# normals, unlike any other application working with meshes which use
# counter-clockwise ordered vertices to create outward pointing normals.


def polyhedron(filename: str):
    doc = ezdxf.new()
    doc.layers.add("NORMALS", color=3)
    msp = doc.modelspace()

    sponge = MengerSponge(level=3).mesh()
    sponge.flip_normals()  # important for OpenSCAD
    sphere = forms.sphere(
        count=32, stacks=16, radius=0.5, quads=True
    ).translate(0.25, 0.25, 1)
    sphere.flip_normals()  # important for OpenSCAD

    script = openscad.boolean_operation(openscad.DIFFERENCE, sponge, sphere)
    result = openscad.run(script)
    print("Result has:")
    print(f"{len(result.vertices)} vertices")
    print(f"{len(result.faces)} faces")
    result.render_mesh(msp)

    # The exported mesh from OpenSCAD has outward pointing normals, so flipping
    # normals is not necessary!
    result.render_normals(msp, length=0.1, dxfattribs={"layer": "NORMALS"})

    doc.set_modelspace_vport(6, center=(5, 0))
    doc.saveas(filename)
    print(f"exported DXF file: '{filename}'")


if __name__ == "__main__":
    polyhedron(POLYHEDRON)
    polygon(POLYGON)