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 86 87 88 89 90 91
|
# Copyright (c) 2022, Manfred Moitzi
# License: MIT License
from typing import Sequence
import pathlib
import ezdxf
from ezdxf.math import Vec3
from ezdxf.render import forms, MeshTransformer
from ezdxf.addons import meshex, 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.
#
# docs: https://ezdxf.mozman.at/docs/addons/openscad.html
# ------------------------------------------------------------------------------
def make_rect_room(
length: float, width: float, height: float, wall_thickness: float
):
wall_thickness2 = 2 * wall_thickness
outer_polygon = forms.box(length, width)
inner_polygon = forms.box(
length - wall_thickness2, width - wall_thickness2
)
outer_box = make_polyhedron(outer_polygon, height)
inner_box = make_polyhedron(inner_polygon, height)
inner_box.translate(wall_thickness, wall_thickness, 0)
return outer_box, inner_box
def make_polyhedron(vertices: Sequence[Vec3], height: float) -> MeshTransformer:
# create polyhedrons from contours like polylines
height_vec = Vec3(0, 0, height)
bottom_profile = list(vertices)
top_profile = list(forms.translate(bottom_profile, height_vec))
return forms.from_profiles_linear([bottom_profile, top_profile], caps=True)
def walls_by_openscad() -> MeshTransformer:
# create 3 rectangular rooms from an outer box minus an inner box
o1, i1 = make_rect_room(10, 5, 2.6, 0.3)
o2, i2 = o1.copy().translate(15, 0, 0), i1.copy().translate(15, 0, 0)
o3, i3 = o1.copy().translate(7.5, 2.5, 0), i1.copy().translate(7.5, 2.5, 0)
# Flipping the normals for OpenSCAD is best practice, but this
# example works also without that.
for m in (o1, o2, o3, i1, i2, i3):
m.flip_normals()
"""
// https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/CSG_Modelling
// create an OpenSCAD script like this:
difference() {
union() { // add all outer boxes
o1;
o2;
o3;
} // and subtract all inner boxes
i1;
i2;
i3;
}
"""
script = openscad.Script()
script.add("difference() { union() {")
script.add_polyhedron(o1)
script.add_polyhedron(o2)
script.add_polyhedron(o3)
script.add("}")
script.add_polyhedron(i1)
script.add_polyhedron(i2)
script.add_polyhedron(i3)
script.add("}")
return openscad.run(script.get_string())
def main(filename: str):
doc = ezdxf.new()
msp = doc.modelspace()
wall_mesh = walls_by_openscad()
wall_mesh.render_mesh(msp, dxfattribs={"layer": "WALL_MESH"})
doc.saveas(CWD / (filename + ".dxf"))
with open(CWD / (filename + ".obj"), "wt") as fp:
fp.write(meshex.obj_dumps(wall_mesh))
if __name__ == "__main__":
main("walls3d_openscad")
|