Source code for ilpm.dxf

#!/usr/bin/env python
from numpy import *

'''Class for outputting dxf files from python.
-Dustin Kleckner c.2012, Noah Mitchell 2017
'''


[docs]class DXF: """Class for handling dxf files using python. DXF is a vector graphics format widely used in CAD applications.""" def __init__(self): """Initialize the dxf instance, with attributes 'contents' 'closing' and 'preview'""" self.contents = [0, 'SECTION', 2, 'ENTITIES'] self.closing = [0, 'ENDSEC', 0, 'EOF'] self.preview = []
[docs] def save(self, fn): """Output the dxf instance to a dxf file""" f = open(fn, 'wt') f.write('\n'.join(map(str, self.contents + self.closing)))
[docs] def line(self, x0, y0, x1, y1, layer='0'): """Create a line segment in the dxf instance Parameters ---------- x0 : float starting x coordinate for lineseg y0 : float starting y coordinate for lineseg x1 : float ending x coordinate for lineseg y1 : float ending y coordinate for lineseg layer : str (default='0') which layer of the dxf vector graphics image to add line to """ self.contents += [0, 'LINE', 8, layer, 10, x0, 20, y0, 11, x1, 21, y1] self.preview.append(array([(x0, y0), (x1, y1)]))
[docs] def polyline(self, X, layer='0', closed=False): """Create a sequence of line segments in the dxf instance Parameters ---------- X : length N list of length 2 lists of floats or N x 2 float array the sequence of points for which to create linesegments, in order layer : str (default='0') which layer of the dxf vector graphics image to add line to closed : bool whether to connect X[-1] to X[0] as a lineseg """ X = asarray(X) for i, x in enumerate(X): ip = i + 1 if ip == len(X): if closed: ip = 0 else: break xp = X[ip] self.line(x[0], x[1], xp[0], xp[1], layer) if closed: X = vstack([X, X[:1]]) self.preview.append(X)
[docs] def circle(self, X, r, layer='0', preview_points=200): """Create a circle in the dxf instance Parameters ---------- X : length 2 list of floats or 2 x 1 float array the center point for the circle to create r : float the radius of the circle layer : str (default='0') which layer of the dxf vector graphics image to add line to preview_points : int how many points with which to approximate the circle in the preview (the actual dxf file has a true vector graphics circle) """ self.contents += [0, 'CIRCLE', 8, layer, 10, X[0], 20, X[1], 40, r] phi = arange(preview_points+1) * 2*pi / preview_points self.preview.append(X + r * array([cos(phi), sin(phi)]).T)
[docs] def plot_preview(self, show=True): """Plot the contents of the dxf instance Parameters ---------- show : bool whether to render the figure showing the dxf contents """ import pylab for line in self.preview: pylab.plot(line[:, 0], line[:, 1], '-k') pylab.gca().set_aspect('equal') if show: pylab.show()
if __name__ == '__main__': inch = 25.4 dxf = DXF() #dxf.polyline(5 * circle, closed=True) dxf.circle([0, 0], 2.5*inch) dxf.circle([5*inch, 0], 2.5*inch) for phi in arange(8) * 2*pi / 8: dxf.circle(array([cos(phi), sin(phi)]) * 2.25 * inch, 0.08 * inch) dxf.circle((array([cos(phi), sin(phi)]) * 2.25 + (5, 0)) * inch, 0.08 * inch) N = 500 phi = arange(N) * 2 * pi / N circle = array((cos(phi), sin(phi))).T dxf.polyline(circle * (25 + 25/4.*cos(3*phi).reshape((N, 1))), closed=True) dxf.circle([5*inch -30, 0], 15) dxf.circle([5*inch +30, 0], 15) #dxf.circle([0, 0], 2*inch) dxf.plot_preview() #dxf.save('two_vortex_masks.dxf')