adjustments in path2openscad

This commit is contained in:
leyghisbb 2021-05-14 00:08:41 +02:00
parent 1ab46d13b7
commit e988ae202f
2 changed files with 143 additions and 202 deletions

View File

@ -4,27 +4,16 @@
<id>fablabchemnitz.de.paths2openscad</id>
<param name="tab" type="notebook">
<page name="splash" gui-text="Paths to OpenSCAD">
<param type="path" name="fname" gui-text="Ausgabedatei" mode="file_new" filetypes="scad">{NAME}.scad</param>
<label>Use "{NAME}.scad" here to use the name from svg.</label>
<param name="zsize" type="float" min="0" max="1000" precision="2" gui-text="Depth (Z) [mm]">5.0</param>
<label>Default 3D extrude depth (when no zsize is parsed from an svg object).</label>
<param name="parsedesc" type="bool" gui-text="Description parsing">true</param>
<label>Read the extruded zsize, zoffset, scale per svg object from its description or ID. See the Extrusion Syntax tab for details.</label>
<spacer/>
<param name="scadview" type="bool" gui-text="View in OpenSCAD">false</param>
<label>Start OpenSCAD to view the 3D-model.</label>
<spacer/>
<param name="scad2stl" type="bool" gui-text="Convert to STL">false</param>
<label>Also save an .stl file next to the specified output file.</label>
<spacer/>
<param name="stlpost" type="bool" gui-text="STL postprocessing">false</param>
<label>Start e.g. a slicer after converting to STL. See the Commands tab for details.</label>
<param type="path" name="fname" gui-text="Output file" mode="file_new" filetypes="scad" gui-description="Use '{NAME}.scad' here to use the name from svg.">{NAME}.scad</param>
<param name="zsize" type="float" min="0" max="1000" precision="2" gui-text="Depth (Z) [mm]" gui-description="Default 3D extrude depth (when no zsize is parsed from an svg object).">5.0</param>
<param name="parsedesc" type="bool" gui-text="Description parsing" gui-description="Read the extruded zsize, zoffset, scale per svg object from its description or ID. See the Extrusion Syntax tab for details.">true</param>
<param name="scadview" type="bool" gui-text="View in OpenSCAD" gui-description="Start OpenSCAD to view the 3D-model.">false</param>
<param name="scad2stl" type="bool" gui-text="Convert to STL" gui-description="Also save an .stl file next to the specified output file.">false</param>
<param name="stlpost" type="bool" gui-text="STL post processing" gui-description="Start e.g. a slicer after converting to STL. See the Commands tab for details.">false</param>
<param name="stlmodule" type="bool" gui-text="Only create a module">false</param>
<spacer/>
</page>
<page name="tuning" gui-text="Tuning">
<param name="smoothness" type="float" min="0.0001" max="5" precision="4" gui-text="Smoothing">0.2</param>
<label>Used when rendering curves. Smaller values are smoother. Range: 0.0001 to 5</label>
<param name="smoothness" type="float" min="0.0001" max="5" precision="4" gui-text="Smoothing" gui-description="Used when rendering curves. Smaller values are smoother. Range: 0.0001 to 5">0.2</param>
<param type="float" name="chamfer" min="0.0" gui-text="Add chamfer radius [mm]">0</param>
<param name="chamfer_fn" type="optiongroup" appearance="combo" gui-text="Chamfer precision ($fn)">
<option value="4">4: Rough (fast)</option>
@ -33,9 +22,7 @@
<option value="32">32: Perfekt (slowest)</option>
</param>
<label appearance="header">Outline Mode</label>
<label xml:space="preserve">Objects are extruded into 3D either in normal mode, or in outline mode. Normally filled areas are extruded, ignoring the line width. Objects with no fill are rendered in outline mode.
Note: the 'Scale: XX %' instruction has no effect in outline mode.</label>
<label>Objects are extruded into 3D either in normal mode, or in outline mode. Normally filled areas are extruded, ignoring the line width. Objects with no fill are rendered in outline mode. Note: the 'Scale: XX %' instruction has no effect in outline mode.</label>
<param name="min_line_width" type="float" min="0.1" max="10" gui-text="Minimum line width [mm]">1.0</param>
<param type="float" name="line_width_scale_perc" min="1" max="10000" gui-text="Scale line width [%]">100.0</param>
<param name="line_fn" type="optiongroup" appearance="combo" gui-text="Line width precision ($fn)">
@ -49,22 +36,9 @@ Note: the 'Scale: XX %' instruction has no effect in outline mode.</label>
</page>
<page name="commands" gui-text="Commands">
<label>Placeholders: You can use "{NAME}.scad" for the OpenSCAD file to read as specified as 'Output file' in the main tab. You can use "{NAME}.stl" for an STL file to write.</label>
<label>Beware, Windows and Mac users: The shipped defaults are for Linux.</label>
<label>Mac: /Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD</label>
<spacer/>
<!-- CAUTION: keep this command in sync with the default INX_SCADVIEW in paths2openscad.py -->
<param name="scadviewcmd" type="string" gui-text="View in OpenSCAD: ">openscad "{NAME}.scad"</param>
<label>Is only started, if no command of the same name is running. Always started non-blocking. A running OpenSCAD automatically picks up changed file contents. Defaults:</label>
<label>Linux: openscad "{NAME}.scad"</label>
<spacer/>
<!-- CAUTION: keep this command in sync with the default INX_SCAD2STL in paths2openscad.py -->
<param name="scad2stlcmd" type="string" gui-text="Convert to STL: ">openscad "{NAME}.scad" -o "{NAME}.stl"</param>
<label>Automatically run, when STL postprocessing is requested.</label>
<spacer/>
<!-- CAUTION: keep this command in sync with the default INX_STL_POSTPROCESSING in paths2openscad.py -->
<param name="stlpostcmd" type="string" gui-text="STL postprocessing: ">cura "{NAME}.stl" &amp;</param>
<label>Append an "&amp;" for non-blocking.</label>
<spacer/>
<param name="scadviewcmd" type="string" gui-text="View in OpenSCAD:" gui-description="Is only started, if no command of the same name is running. Always started non-blocking. A running OpenSCAD automatically picks up changed file content">openscad "{NAME}.scad"</param>
<param name="scad2stlcmd" type="string" gui-text="Convert to STL:" gui-description="Automatically run, when STL postprocessing is requested.">openscad "{NAME}.scad" -o "{NAME}.stl"</param>
<param name="stlpostcmd" type="string" gui-text="STL postprocessing:" gui-description="Append an '&amp;' for non-blocking.">cura "{NAME}.stl" &amp;</param>
</page>
<page name="extrusion" gui-text="Extrusion Syntax">
<label xml:space="preserve">The depth (Z-Axis) and other parameters can be defined through an svg object's description. The menu 'Object-&gt;Object Properties ...' (Shift-Ctrl-O) shows details of one selected object.
@ -95,26 +69,16 @@ Parameters in the objects take precedence over groups.</label>
</page>
<page name="info" gui-text="About ...">
<label xml:space="preserve">
This extension converts Inkscape paths to
extruded polygons in OpenSCAD. Before
using, some objects must firat be converted to paths
with the "Path &gt; Object to Path" menu item.
This extension converts Inkscape paths to extruded polygons in OpenSCAD. Before using, some objects must firat be converted to paths with the "Path &gt; Object to Path" menu item.
Inkscape's units of pixels are converted
to millimeters using the SVG standard's
definition of 96 px = 1 inch = 25.4 mm.
(Before inkscape 0.92 the standard was 90 px per inch,
Adobe products often use 75 px per inch)
Inkscape's units of pixels are converted to millimeters using the SVG standard's definition of 96 px = 1 inch = 25.4 mm. (Before inkscape 0.92 the standard was 90 px per inch, Adobe products often use 75 px per inch)
v0.25
Dan Newman (dan newman @ mtbaldy us)
Josef Skladanka (jskladan @ redhat com)
Juergen Weigert (juergen @ fabmail org)
Find updates at https://github.com/fablabnbg/inkscape-paths2openscad/releases
<!-- keep the version numnber in sync with paths2openscad.py header comments and translated copies -->
</label>
Find updates at</label>
<label appearance="url">https://github.com/fablabnbg/inkscape-paths2openscad/releases</label>
</page>
</param>
<effect needs-live-preview="false">

View File

@ -125,6 +125,7 @@ import time
import string
import tempfile
import gettext
import subprocess
VERSION = "0.27" # CAUTION: Keep in sync with all *.inx files
DEFAULT_WIDTH = 100
@ -147,9 +148,9 @@ RE_AUTO_ZOFFSET_DESC = re.compile(
DESC_TAGS = ["desc", inkex.addNS("desc", "svg")]
# CAUTION: keep these defaults in sync with paths2openscad.inx
INX_SCADVIEW = os.getenv("INX_SCADVIEW", "openscad '{NAME}.scad'")
INX_SCAD2STL = os.getenv("INX_SCAD2STL", "openscad '{NAME}.scad' -o '{NAME}.stl'")
INX_STL_POSTPROCESSING = os.getenv("INX_STL_POSTPROCESSING", "cura '{NAME}.stl' &")
INX_SCADVIEW = os.getenv("INX_SCADVIEW", "openscad \"{NAME}.scad\"")
INX_SCAD2STL = os.getenv("INX_SCAD2STL", "openscad \"{NAME}.scad\" -o \"{NAME}.stl\"")
INX_STL_POSTPROCESSING = os.getenv("INX_STL_POSTPROCESSING", "cura \"{NAME}.stl\" &")
def IsProcessRunning(pid):
@ -158,19 +159,12 @@ def IsProcessRunning(pid):
"""
sys_platform = sys.platform.lower()
if sys_platform.startswith("win"):
import subprocess
ps = subprocess.Popen(
r'tasklist.exe /NH /FI "PID eq %d"' % (pid),
shell=True,
stdout=subprocess.PIPE,
)
output = ps.stdout.read()
ps.stdout.close()
ps.wait()
if str(pid) in output:
return True
return False
with subprocess.Popen(r'tasklist.exe /NH /FI "PID eq %d"' % (pid), shell=True, stdout=subprocess.PIPE) as ps:
output = ps.stdout.read()
ps.wait()
if str(pid) in output:
return True
return False
else:
# OSX sys_platform.startswith('darwin'):
# and Linux
@ -433,15 +427,15 @@ class OpenSCAD(inkex.EffectExtension):
pars.add_argument( "--line_fn", type=int, default=int(4), help="Line width precision ($fn when constructing hull)", )
pars.add_argument( "--force_line", type=inkex.utils.Boolean, default=False, help="Force outline mode.", )
pars.add_argument( "--fname", default="{NAME}.scad", help="openSCAD output file derived from the svg file name.", )
pars.add_argument( "--parsedesc", default="true", help="Parse zsize and other parameters from object descriptions", )
pars.add_argument( "--scadview", default="false", help="Open the file with openscad ( details see --scadviewcmd option )", )
pars.add_argument( "--parsedesc", type=inkex.utils.Boolean, default=True, help="Parse zsize and other parameters from object descriptions", )
pars.add_argument( "--scadview", type=inkex.utils.Boolean, default=False, help="Open the file with openscad ( details see --scadviewcmd option )", )
pars.add_argument( "--scadviewcmd", default=INX_SCADVIEW, help="Command used start an openscad viewer. Use {SCAD} for the openSCAD input.", )
pars.add_argument( "--scad2stl", default="false", help="Also convert to STL ( details see --scad2stlcmd option )", )
pars.add_argument( "--scad2stl", type=inkex.utils.Boolean, default=False, help="Also convert to STL ( details see --scad2stlcmd option )", )
pars.add_argument( "--scad2stlcmd", default=INX_SCAD2STL, help="Command used to convert to STL. You can use {NAME}.scad for the openSCAD file to read and "
+ "{NAME}.stl for the STL file to write.", )
pars.add_argument( "--stlpost", default="false", help="Start e.g. a slicer. This implies the --scad2stl option. ( see --stlpostcmd )", )
pars.add_argument( "--stlpost", type=inkex.utils.Boolean, default=False, help="Start e.g. a slicer. This implies the --scad2stl option. ( see --stlpostcmd )", )
pars.add_argument( "--stlpostcmd", default=INX_STL_POSTPROCESSING, help="Command used for post processing an STL file (typically a slicer). You can use {NAME}.stl for the STL file.", )
pars.add_argument( "--stlmodule",default="false", help="Output configured to comment out final rendering line, to create a module file for import.", )
pars.add_argument( "--stlmodule", type=inkex.utils.Boolean, default=False, help="Output configured to comment out final rendering line, to create a module file for import.", )
self.userunitsx = 1.0 # Move to pure userunits per mm for v1.0
self.userunitsy = 1.0
@ -463,7 +457,7 @@ class OpenSCAD(inkex.EffectExtension):
self.pathid = int(0)
# Output file
self.f = None
self.outfile = None
# For handling an SVG viewbox attribute, we will need to know the
# values of the document's <svg> width and height attributes as well
@ -793,8 +787,8 @@ class OpenSCAD(inkex.EffectExtension):
)
polypoints = polypoints[:-1]
polypoints += "];\n"
self.f.write(polycenter + ";\n")
self.f.write(polypoints)
self.outfile.write(polycenter + ";\n")
self.outfile.write(polypoints)
prefix += 1
else:
# This subpath contains other subpaths
@ -824,22 +818,22 @@ class OpenSCAD(inkex.EffectExtension):
polypoints += "];\n"
polypaths = polypaths[:-7] + "];\n"
# write the polys and paths
self.f.write(polycenter + ";\n")
self.f.write(polypoints)
self.f.write(polypaths)
self.outfile.write(polycenter + ";\n")
self.outfile.write(polypoints)
self.outfile.write(polypaths)
prefix += 1
# #### end global data for msg_*() functions. ####
self.f.write("module poly_" + id + "(h, w, s, res=line_fn)\n{\n")
self.outfile.write("module poly_" + id + "(h, w, s, res=line_fn)\n{\n")
# Element is transformed to correct size, so scale is now just for the user to
# tweak after the fact
self.f.write(" scale([custom_scale_x, -custom_scale_y, 1]) union()\n {\n")
self.outfile.write(" scale([custom_scale_x, -custom_scale_y, 1]) union()\n {\n")
# And add the call to the call list
# Z-size is set by the overall module parameter
# unless an extrusion zsize is parsed from the description or ID.
extrusion = {"zsize": "h", "zoffset": "0", "scale": 100.0, "neg": False}
if self.options.parsedesc == "true":
if self.options.parsedesc is True:
object_merge_extrusion_values(extrusion, node)
call_item = "translate ([0,0,%s]) poly_%s(%s, min_line_mm(%s), %s);\n" % (
@ -883,11 +877,11 @@ class OpenSCAD(inkex.EffectExtension):
# This subpath contains other subpaths
poly = msg_extrude_by_hull_and_paths(id, prefix)
self.f.write(poly)
self.outfile.write(poly)
prefix += 1
# End the module
self.f.write(" }\n}\n")
self.outfile.write(" }\n}\n")
def recursivelyTraverseSvg(
self, aNodeList, matCurrent=Transform(None), parent_visibility="visible"
@ -1198,11 +1192,7 @@ class OpenSCAD(inkex.EffectExtension):
pass
def recursivelyGetEnclosingTransform(self, node):
"""
Determine the cumulative transform which node inherits from
its chain of ancestors.
"""
# Determine the cumulative transform which node inherits from its chain of ancestors.
node = node.getparent()
if node is not None:
parent_transform = self.recursivelyGetEnclosingTransform(node)
@ -1250,13 +1240,13 @@ class OpenSCAD(inkex.EffectExtension):
scad_fname = os.path.expanduser(self.options.fname)
if "/" != os.sep:
scad_fname = scad_fname.replace("/", os.sep)
self.f = open(scad_fname, "w")
self.outfile = open(scad_fname, "w")
self.f.write(
self.outfile.write(
"// Generated by inkscape %s + inkscape-paths2openscad %s\n"
% (self.inkscape_version, VERSION)
)
self.f.write('// %s from "%s.svg"\n' % (time.ctime(), self.basename))
self.outfile.write('// %s from "%s.svg"\n' % (time.ctime(), self.basename))
# for use in options.fname basename is derived from the sodipodi_docname by
# stripping the svg extension - or if there is no sodipodi_docname basename is 'inkscape'.
@ -1264,7 +1254,7 @@ class OpenSCAD(inkex.EffectExtension):
# options.fname by stripping an scad extension.
self.basename = re.sub(r"\.scad", "", scad_fname, flags=re.I)
self.f.write(
self.outfile.write(
"""
// Module names are of the form poly_<inkscape-path-id>(). As a result,
// you can associate a polygon in this OpenSCAD program with the corresponding
@ -1280,32 +1270,32 @@ fudge = 0.1;
if self.options.chamfer < 0.001:
self.options.chamfer = None
self.f.write("user_unit_scale_x = %s;\n" % (self.userunitsx))
self.f.write("user_unit_scale_y = %s;\n" % (self.userunitsy))
self.f.write("custom_scale_x = 1;\n")
self.f.write("custom_scale_y = 1;\n")
self.outfile.write("user_unit_scale_x = %s;\n" % (self.userunitsx))
self.outfile.write("user_unit_scale_y = %s;\n" % (self.userunitsy))
self.outfile.write("custom_scale_x = 1;\n")
self.outfile.write("custom_scale_y = 1;\n")
# writeout users parameters
self.f.write("zsize = %s;\n" % (self.options.zsize))
self.f.write("line_fn = %d;\n" % (self.options.line_fn))
self.outfile.write("zsize = %s;\n" % (self.options.zsize))
self.outfile.write("line_fn = %d;\n" % (self.options.line_fn))
if self.options.chamfer:
self.f.write("chamfer = %s;\n" % (self.options.chamfer))
self.f.write("chamfer_fn = %d;\n" % (self.options.chamfer_fn))
self.f.write("min_line_width = %s;\n" % (self.options.min_line_width))
self.f.write(
self.outfile.write("chamfer = %s;\n" % (self.options.chamfer))
self.outfile.write("chamfer_fn = %d;\n" % (self.options.chamfer_fn))
self.outfile.write("min_line_width = %s;\n" % (self.options.min_line_width))
self.outfile.write(
"line_width_scale = %s;\n" % (self.options.line_width_scale_perc * 0.01)
)
self.f.write(
self.outfile.write(
"function min_line_mm(w) = max(min_line_width, w * line_width_scale) * %g;\n\n"
% self.userunitsx
)
for key in self.paths:
self.f.write("\n")
self.outfile.write("\n")
self.convertPath(key)
if self.options.chamfer:
self.f.write(
self.outfile.write(
"""
module chamfer_sphere(rad=chamfer, res=chamfer_fn)
{
@ -1330,81 +1320,77 @@ module chamfer_sphere(rad=chamfer, res=chamfer_fn)
badchars = string.punctuation.replace("_", "") + " "
name = re.sub("[" + badchars + "]", "_", name)
self.f.write("\nmodule %s(h)\n{\n" % name)
self.outfile.write("\nmodule %s(h)\n{\n" % name)
mi = ""
if self.options.chamfer:
mi = " "
self.f.write(" minkowski()\n {\n")
self.outfile.write(" minkowski()\n {\n")
# Now output the list of modules to call
self.f.write(
self.outfile.write(
"%s difference()\n%s {\n%s union()\n%s {\n" % (mi, mi, mi, mi)
)
for call in self.call_list:
self.f.write("%s %s" % (mi, call))
self.f.write("%s }\n%s union()\n%s {\n" % (mi, mi, mi))
self.outfile.write("%s %s" % (mi, call))
self.outfile.write("%s }\n%s union()\n%s {\n" % (mi, mi, mi))
for call in self.call_list_neg:
self.f.write("%s %s" % (mi, call))
self.f.write("%s }\n%s }\n" % (mi, mi))
self.outfile.write("%s %s" % (mi, call))
self.outfile.write("%s }\n%s }\n" % (mi, mi))
if self.options.chamfer:
self.f.write(" chamfer_sphere();\n }\n")
self.outfile.write(" chamfer_sphere();\n }\n")
# The module that calls all the other ones.
if self.options.stlmodule == "true":
self.f.write("}\n\n//%s(zsize);\n" % (name))
if self.options.stlmodule is True:
self.outfile.write("}\n\n//%s(zsize);\n" % (name))
else:
self.f.write("}\n\n%s(zsize);\n" % (name))
self.f.close()
self.outfile.write("}\n\n%s(zsize);\n" % (name))
except IOError as e:
inkex.errormsg("Unable to write file " + self.options.fname)
inkex.errormsg("ERROR: " + str(e))
self.outfile.close()
if self.options.scadview == "true":
################################################################
# Call OpenSCAD
################################################################
if self.options.scadview is True:
pidfile = os.path.join(tempfile.gettempdir(), "paths2openscad.pid")
running = False
cmd = self.options.scadviewcmd.format(
**{"SCAD": scad_fname, "NAME": self.basename}
)
cmd = self.options.scadviewcmd.format(**{"SCAD": scad_fname, "NAME": self.basename})
try:
pfile=open(pidfile)
m = re.match(r"(\d+)\s+(.*)", pfile.read())
pfile.close()
oldpid = int(m.group(1))
oldcmd = m.group(2)
# print >> sys.stderr, "pid {1} seen in {0}".format(pidfile, oldpid)
# print >> sys.stderr, "cmd {0}, oldcmd {1}".format(cmd, oldcmd)
if cmd == oldcmd:
# we found a pidfile and the cmd in there is still identical.
# If we change the filename in the inkscape extension gui, the cmd differs, and
# the still running openscad would not pick up our changes.
# If the command is identical, we check if the pid in the pidfile is alive.
# If so, we assume, the still running openscad will pick up the changes.
#
# WARNING: too much magic here. We cannot really test, if the last assumption holds.
# Comment out the next line to always start a new instance of openscad.
running = IsProcessRunning(oldpid)
# print >> sys.stderr, "running {0}".format(running)
with open(pidfile) as pfile:
m = re.match(r"(\d+)\s+(.*)", pfile.read())
oldpid = int(m.group(1))
oldcmd = m.group(2)
# print >> sys.stderr, "pid {1} seen in {0}".format(pidfile, oldpid)
# print >> sys.stderr, "cmd {0}, oldcmd {1}".format(cmd, oldcmd)
if cmd == oldcmd:
# we found a pidfile and the cmd in there is still identical.
# If we change the filename in the inkscape extension gui, the cmd differs, and
# the still running openscad would not pick up our changes.
# If the command is identical, we check if the pid in the pidfile is alive.
# If so, we assume, the still running openscad will pick up the changes.
#
# WARNING: too much magic here. We cannot really test, if the last assumption holds.
# Comment out the next line to always start a new instance of openscad.
running = IsProcessRunning(oldpid)
# print >> sys.stderr, "running {0}".format(running)
except Exception:
pass
if not running:
import subprocess
try:
tty = open("/dev/tty", "w")
except Exception:
tty = subprocess.PIPE
try:
proc = subprocess.Popen(cmd, shell=True, stdin=tty, stdout=tty, stderr=tty)
proc.wait()
tty.close()
with subprocess.Popen(cmd, shell=True, stdin=tty, stdout=tty, stderr=tty) as proc:
proc.wait()
except OSError as e:
raise OSError("%s failed: errno=%d %s" % (cmd, e.errno, e.strerror))
try:
pfile = open(pidfile, "w")
pfile.write(str(proc.pid) + "\n" + cmd + "\n")
pfile.close()
with open(pidfile, "w") as pfile:
pfile.write(str(proc.pid) + "\n" + cmd + "\n")
except Exception:
pass
else:
@ -1414,71 +1400,62 @@ module chamfer_sphere(rad=chamfer, res=chamfer_fn)
# pick up the changes. and we have no way to tell the difference if it did.
pass
if self.options.scad2stl == "true" or self.options.stlpost == "true":
################################################################
# Call OpenSCAD to STL conversion
################################################################
if self.options.scad2stl is True or self.options.stlpost is True:
stl_fname = self.basename + ".stl"
cmd = self.options.scad2stlcmd.format(
**{"SCAD": scad_fname, "STL": stl_fname, "NAME": self.basename}
)
scad2stlcmd = self.options.scad2stlcmd.format(**{"SCAD": scad_fname, "STL": stl_fname, "NAME": self.basename})
try:
os.unlink(stl_fname)
except Exception:
pass
import subprocess
try:
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with subprocess.Popen(scad2stlcmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
proc.wait()
except OSError as e:
raise OSError(
"{0} failed: errno={1} {2}".format(cmd, e.errno, e.strerror)
)
stdout, stderr = proc.communicate()
len = -1
try:
len = os.path.getsize(stl_fname)
except Exception:
pass
if len < 1000:
inkex.errormsg(
"CMD: {} WARNING: {} is very small: {} bytes.".format(
cmd, stl_fname, len
)
)
inkex.errormsg("= " * 24)
inkex.errormsg("STDOUT:\n{}".format(stdout))
inkex.errormsg("= " * 24)
inkex.errormsg("STDERR:\n{}".format(stderr))
inkex.errormsg("= " * 24)
if len <= 0: # something is wrong. better stop here
self.options.stlpost = "false"
proc.wait()
if self.options.stlpost == "true":
cmd = self.options.stlpostcmd.format(
**{"STL": self.basename + ".stl", "NAME": self.basename}
)
try:
tty = open("/dev/tty", "w")
except Exception:
tty = subprocess.PIPE
try:
proc = subprocess.Popen(cmd, shell=True, stdin=tty, stdout=tty, stderr=tty)
proc.wait()
except OSError as e:
raise OSError("%s failed: errno=%d %s" % (cmd, e.errno, e.strerror))
stdout, stderr = proc.communicate()
if stdout or stderr:
inkex.errmsg("CMD: {}".format(cmd))
len = -1
try:
len = os.path.getsize(stl_fname)
except Exception:
pass
if len < 1000:
inkex.errormsg("CMD: {} WARNING: {} is very small: {} bytes.".format(scad2stlcmd, stl_fname, len))
inkex.errormsg("= " * 24)
if stdout:
inkex.errmsg("STDOUT: {}".format(stdout))
inkex.errormsg("STDOUT:\n{}".format(stdout))
inkex.errormsg("= " * 24)
if stderr:
inkex.errmsg("STDERR: {}".format(stderr))
inkex.errormsg("STDERR:\n{}".format(stderr))
inkex.errormsg("= " * 24)
if len <= 0: # something is wrong. better stop here
self.options.stlpost = False
################################################################
# Call OpenSCAD post processing
################################################################
if self.options.stlpost is True:
stlpostcmd = self.options.stlpostcmd.format(
**{"STL": self.basename + ".stl", "NAME": self.basename}
)
try:
tty = open("/dev/tty", "w")
except Exception:
tty = subprocess.PIPE
try:
with subprocess.Popen(stlpostcmd, shell=True, stdin=tty, stdout=tty, stderr=tty) as proc:
proc.wait()
stdout, stderr = proc.communicate()
if stdout or stderr:
inkex.errormsg("CMD: {}".format(stlpostcmd))
inkex.errormsg("= " * 24)
if stdout:
inkex.errormsg("STDOUT: {}".format(stdout))
inkex.errormsg("= " * 24)
if stderr:
inkex.errormsg("STDERR: {}".format(stderr))
inkex.errormsg("= " * 24)
except OSError as e:
raise OSError("%s failed: errno=%d %s" % (stlpostcmd, e.errno, e.strerror))
if __name__ == '__main__':
OpenSCAD().run()