Added linux support for DXF/DWG Importer
This commit is contained in:
parent
8462fd07ae
commit
defa65e0f1
@ -8,7 +8,7 @@
|
|||||||
<label>The parser is the heart of your input-output chain because depending on the selection your result will greatly vary. You might receive no or bad results (e.g. wrong scalings, aborted imports, missing lines, duplicated lines, wrong rotations and other issues. Serious tip: ask the person who gave the input file to you about some measurement which you can compare with the processed file to ensure correct sizes)</label>
|
<label>The parser is the heart of your input-output chain because depending on the selection your result will greatly vary. You might receive no or bad results (e.g. wrong scalings, aborted imports, missing lines, duplicated lines, wrong rotations and other issues. Serious tip: ask the person who gave the input file to you about some measurement which you can compare with the processed file to ensure correct sizes)</label>
|
||||||
<param name="dxf_to_svg_parser" gui-text="DXF to SVG parser" type="optiongroup" appearance="combo">
|
<param name="dxf_to_svg_parser" gui-text="DXF to SVG parser" type="optiongroup" appearance="combo">
|
||||||
<option value="bjnortier">bjnortier DXF (good quality, some polygon artifacts)</option>
|
<option value="bjnortier">bjnortier DXF (good quality, some polygon artifacts)</option>
|
||||||
<option value="uniconverter">sk1 UniConverter (best output, but fails for all unknown/unfiltered entities)</option>
|
<option value="sk1">sk1 UniConverter (best output, but fails for all unknown/unfiltered entities)</option>
|
||||||
<option value="ezdxf">ezdxf (higher quality, many single nodes)</option>
|
<option value="ezdxf">ezdxf (higher quality, many single nodes)</option>
|
||||||
<option value="legacy">legacy InkScape importer</option>
|
<option value="legacy">legacy InkScape importer</option>
|
||||||
</param>
|
</param>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
</page>
|
</page>
|
||||||
<page name="dwg_dxf" gui-text="DWG to DXF / DXF to DXF">
|
<page name="dwg_dxf" gui-text="DWG to DXF / DXF to DXF">
|
||||||
<label appearance="header">Open Design Alliance (ODA) File Converter</label>
|
<label appearance="header">Open Design Alliance (ODA) File Converter</label>
|
||||||
<param name="oda_fileconverter" type="path" gui-text="ODAFileConverter.exe" gui-description="Full path to 'ODAFileConverter executable'" filetypes="" mode="file">C:\Program Files\ODA\ODAFileConverter_title 21.6.0\ODAFileConverter.exe</param>
|
<param name="oda_fileconverter" type="path" gui-text="ODAFileConverter executable" gui-description="Full path to 'ODAFileConverter' executable. On Linux this usually should be '/usr/bin/ODAFileConverter' and on Windows it's 'C:\Program Files\ODA\OdaFileConverter_title XX.Y.Z\ODAFileConverter.exe'" filetypes="" mode="file">C:\Program Files\ODA\ODAFileConverter_title 21.6.0\ODAFileConverter.exe</param>
|
||||||
<param name="oda_keepconverted_dxf" type="bool" gui-text="Keep ODA converted DXF file" gui-description="Will put a copy of the converted DXF into the directory where your input file is located.">true</param>
|
<param name="oda_keepconverted_dxf" type="bool" gui-text="Keep ODA converted DXF file" gui-description="Will put a copy of the converted DXF into the directory where your input file is located.">true</param>
|
||||||
<param name="oda_outputformat" gui-text="AutoCAD output version" type="optiongroup" appearance="combo">
|
<param name="oda_outputformat" gui-text="AutoCAD output version" type="optiongroup" appearance="combo">
|
||||||
<option value="ACAD2018_DXF">2018 ASCII DXF</option>
|
<option value="ACAD2018_DXF">2018 ASCII DXF</option>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<option value="ACAD10_DXB" >R10 Binary DXF</option>
|
<option value="ACAD10_DXB" >R10 Binary DXF</option>
|
||||||
-->
|
-->
|
||||||
</param>
|
</param>
|
||||||
<param name="oda_hidewindow" type="bool" gui-text="Hide ODA GUI window" gui-description="Hide ODA GUI window">true</param>
|
<param name="oda_hidewindow" type="bool" gui-text="Hide ODA GUI window (Windows OS only)" gui-description="Hide ODA GUI window. This does not work for Linux OS.">true</param>
|
||||||
<param name="oda_skip_dxf_to_dxf" type="bool" gui-text="Skip conversion from DXF to DXF (keep input as is)" gui-description="This will skip ODA File Converter execution if input is already DXF file. If your input is DWG this option will not apply. Might save some seconds of time and maybe prevents errors.">false</param>
|
<param name="oda_skip_dxf_to_dxf" type="bool" gui-text="Skip conversion from DXF to DXF (keep input as is)" gui-description="This will skip ODA File Converter execution if input is already DXF file. If your input is DWG this option will not apply. Might save some seconds of time and maybe prevents errors.">false</param>
|
||||||
<param name="oda_audit_repair" type="bool" gui-text="Perform audit (auto-repair)">true</param>
|
<param name="oda_audit_repair" type="bool" gui-text="Perform audit (auto-repair)">true</param>
|
||||||
</page>
|
</page>
|
||||||
@ -144,10 +144,9 @@
|
|||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
<spacer/>
|
<spacer/>
|
||||||
<label appearance="header">sk1 UniConverter 1.1.X</label>
|
<label appearance="header">sk1 UniConvertor 1.1.X</label>
|
||||||
<label>sk1 UniConverter is only available for Windows platforms.</label>
|
|
||||||
<separator/>
|
<separator/>
|
||||||
<param name="sk1_uniconverter" type="path" gui-text="uniconvertor.cmd" gui-description="Full path to 'uniconvertor.cmd'" filetypes="cmd" mode="file">C:\Program Files (x86)\sK1 Project\UniConvertor-1.1.6\uniconvertor.cmd</param>
|
<param name="sk1_uniconverter" type="path" gui-text="uniconvertor executable" gui-description="Full path to 'uniconvertor' executable" filetypes="cmd" mode="file">C:\Program Files (x86)\sK1 Project\UniConvertor-1.1.6\uniconvertor.cmd</param>
|
||||||
<param name="opendironerror" type="bool" gui-text="Open containing output directory on conversion errors">true</param>
|
<param name="opendironerror" type="bool" gui-text="Open containing output directory on conversion errors">true</param>
|
||||||
</page>
|
</page>
|
||||||
</param>
|
</param>
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
"""
|
"""
|
||||||
Extension for InkScape 1.0
|
Extension for InkScape 1.0
|
||||||
|
|
||||||
Import any DWG or DXF file using ODA File Converter, sk1 UniConverter, ezdxf and more tools.
|
Import any DWG or DXF file using ODA File Converter, sk1 UniConvertor, ezdxf and more tools.
|
||||||
|
|
||||||
Author: Mario Voigt / FabLab Chemnitz
|
Author: Mario Voigt / FabLab Chemnitz
|
||||||
Mail: mario.voigt@stadtfabrikanten.org
|
Mail: mario.voigt@stadtfabrikanten.org
|
||||||
Date: 23.08.2020
|
Date: 23.08.2020
|
||||||
Last patch: 24.08.2020
|
Last patch: 28.08.2020
|
||||||
License: GNU GPL v3
|
License: GNU GPL v3
|
||||||
|
|
||||||
Module licenses
|
Module licenses
|
||||||
@ -16,7 +16,7 @@ Module licenses
|
|||||||
- node.js (https://raw.githubusercontent.com/nodejs/node/master/LICENSE) - MIT License
|
- node.js (https://raw.githubusercontent.com/nodejs/node/master/LICENSE) - MIT License
|
||||||
- https://github.com/bjnortier/dxf - MIT License
|
- https://github.com/bjnortier/dxf - MIT License
|
||||||
- ODA File Converter - not bundled (due to restrictions by vendor)
|
- ODA File Converter - not bundled (due to restrictions by vendor)
|
||||||
- sk1 UniConverter (https://github.com/sk1project/uniconvertor) - AGPL v3.0 - not bundled
|
- sk1 UniConvertor (https://github.com/sk1project/uniconvertor) - AGPL v3.0 - not bundled
|
||||||
|
|
||||||
ToDos:
|
ToDos:
|
||||||
- change copy commands to movefile commands (put into temp. sub directories where the input file is located). We need to copy files in this script because ODA File Converter will process whole dirs instead of single files only.DXF files can be really large, which slows the process)
|
- change copy commands to movefile commands (put into temp. sub directories where the input file is located). We need to copy files in this script because ODA File Converter will process whole dirs instead of single files only.DXF files can be really large, which slows the process)
|
||||||
@ -30,9 +30,10 @@ import subprocess, tempfile
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
import shutil
|
import shutil
|
||||||
|
from shutil import which
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from mimetypes import MimeTypes
|
#from mimetypes import MimeTypes
|
||||||
import urllib.request as urllib
|
#import urllib.request as urllib
|
||||||
|
|
||||||
#ezdxf related imports
|
#ezdxf related imports
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
@ -63,7 +64,7 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
self.arg_parser.add_argument("--oda_skip_dxf_to_dxf", type=inkex.Boolean, default=False, help="Skip conversion from DXF to DXF")
|
self.arg_parser.add_argument("--oda_skip_dxf_to_dxf", type=inkex.Boolean, default=False, help="Skip conversion from DXF to DXF")
|
||||||
self.arg_parser.add_argument("--oda_audit_repair", type=inkex.Boolean, default=True, help="Perform audit / autorepair")
|
self.arg_parser.add_argument("--oda_audit_repair", type=inkex.Boolean, default=True, help="Perform audit / autorepair")
|
||||||
|
|
||||||
#sk1 UniConverter
|
#sk1 UniConvertor
|
||||||
self.arg_parser.add_argument("--sk1_uniconverter", default=r"C:\Program Files (x86)\sK1 Project\UniConvertor-1.1.6\uniconvertor.cmd", help="Full path to 'uniconvertor.cmd'")
|
self.arg_parser.add_argument("--sk1_uniconverter", default=r"C:\Program Files (x86)\sK1 Project\UniConvertor-1.1.6\uniconvertor.cmd", help="Full path to 'uniconvertor.cmd'")
|
||||||
self.arg_parser.add_argument("--opendironerror", type=inkex.Boolean, default=True, help="Open containing output directory on conversion errors")
|
self.arg_parser.add_argument("--opendironerror", type=inkex.Boolean, default=True, help="Open containing output directory on conversion errors")
|
||||||
|
|
||||||
@ -114,6 +115,9 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
def effect(self):
|
def effect(self):
|
||||||
#get input file and copy it to some new temporary directory
|
#get input file and copy it to some new temporary directory
|
||||||
inputfile = self.options.inputfile
|
inputfile = self.options.inputfile
|
||||||
|
if not os.path.exists(inputfile):
|
||||||
|
inkex.utils.debug("The input file does not exist. Please select a *.dxf or *.dwg file and try again.")
|
||||||
|
exit(1)
|
||||||
temp_input_dir = os.path.join(tempfile.gettempdir(),"dxfdwg_input")
|
temp_input_dir = os.path.join(tempfile.gettempdir(),"dxfdwg_input")
|
||||||
shutil.rmtree(temp_input_dir, ignore_errors=True) #remove the input directory before doing new job
|
shutil.rmtree(temp_input_dir, ignore_errors=True) #remove the input directory before doing new job
|
||||||
if not os.path.exists(temp_input_dir):
|
if not os.path.exists(temp_input_dir):
|
||||||
@ -196,30 +200,37 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
# Run ODA File Converter
|
# Run ODA File Converter
|
||||||
if self.options.oda_skip_dxf_to_dxf == False or inputfile_ending == ".dwg":
|
if self.options.oda_skip_dxf_to_dxf == False or inputfile_ending == ".dwg":
|
||||||
# Executable test (check for proper configuration by checking mime type. Should return octet stream for a binary executable)
|
# Executable test (check for proper configuration by checking mime type. Should return octet stream for a binary executable)
|
||||||
url = urllib.pathname2url(self.options.oda_fileconverter)
|
if os.name == "nt" and "application/octet-stream" not in str(MimeTypes().guess_type(urllib.pathname2url(self.options.oda_fileconverter))):
|
||||||
if "application/octet-stream" not in str(MimeTypes().guess_type(url)):
|
inkex.utils.debug("ODA File Converter was not properly configured. Check for installation and path location. You can download ODA Converter from 'https://www.opendesign.com/guestfiles/oda_file_converter'")
|
||||||
inkex.utils.debug("ODA File Converter was not properly configured.")
|
exit(1)
|
||||||
|
elif os.path.isfile(self.options.oda_fileconverter) == False:
|
||||||
|
inkex.utils.debug("ODA File Converter was not properly configured. Check for installation and path location. You can download ODA Converter from 'https://www.opendesign.com/guestfiles/oda_file_converter'")
|
||||||
|
exit(1)
|
||||||
else:
|
else:
|
||||||
# Build and run ODA File Converter command
|
# Build and run ODA File Converter command
|
||||||
oda_cmd = [self.options.oda_fileconverter, temp_input_dir, temp_output_dir, autocad_version, autocad_format, "0", self.options.oda_audit_repair]
|
oda_cmd = [self.options.oda_fileconverter, temp_input_dir, temp_output_dir, autocad_version, autocad_format, "0", self.options.oda_audit_repair]
|
||||||
if self.options.oda_hidewindow:
|
if os.name == 'nt' and self.options.oda_hidewindow:
|
||||||
info = subprocess.STARTUPINFO() #hide the ODA File Converter window because it is annoying
|
info = subprocess.STARTUPINFO() #hide the ODA File Converter window because it is annoying (does not work for Linux :-()
|
||||||
info.dwFlags = 1
|
info.dwFlags = 1
|
||||||
info.wShowWindow = 0
|
info.wShowWindow = 0
|
||||||
proc = subprocess.Popen(oda_cmd, startupinfo=info, shell=False, stdout=PIPE, stderr=PIPE)
|
proc = subprocess.Popen(oda_cmd, startupinfo=info, shell=False, stdout=PIPE, stderr=PIPE)
|
||||||
else: proc = subprocess.Popen(oda_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
else:
|
||||||
|
proc = subprocess.Popen(oda_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
||||||
stdout, stderr = proc.communicate()
|
stdout, stderr = proc.communicate()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0 or (len(stderr) > 0 and stderr != b"Quit (core dumped)\n"):
|
||||||
inkex.errormsg("ODA File Converter failed: %d %s %s" % (proc.returncode, stdout, stderr))
|
inkex.utils.debug("ODAFileConverter failed: %d %s %s" % (proc.returncode, stdout, stderr))
|
||||||
|
if os.name != 'nt':
|
||||||
|
inkex.utils.debug("If the error message above contains a warning about wrong/missing Qt version please install the required version. You can get the installer from 'https://download.qt.io/archive/qt/'. Sadly you will need to create a free account to install. After installation please configure the shell script '/usr/bin/ODAFileConverter' to add a preceding line with content similar to 'LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/Qt5.14.2/5.14.2/gcc_64/lib/'.")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Preprocessing DXF to DXF (entity filter)
|
# Do some movings/copies of skipped or processed DXF
|
||||||
if self.options.oda_skip_dxf_to_dxf: #if true we need to move the file to simulate "processed"
|
if self.options.oda_skip_dxf_to_dxf: #if true we need to move the file to simulate "processed"
|
||||||
shutil.move(os.path.join(temp_input_dir, Path(inputfile).name), os.path.join(temp_output_dir, Path(inputfile).name))
|
shutil.move(os.path.join(temp_input_dir, Path(inputfile).name), os.path.join(temp_output_dir, Path(inputfile).name))
|
||||||
|
|
||||||
if self.options.oda_keepconverted_dxf and inputfile_ending != ".dxf": #if the input file already was DXF we don't need to make another copy
|
if self.options.oda_keepconverted_dxf and inputfile_ending != ".dxf": #if the input file already was DXF we don't need to make another copy
|
||||||
shutil.copy2(dxf_file, os.path.join(os.path.dirname(inputfile), outputfilebase + "_oda.dxf")) # complete target filename given
|
shutil.copy2(dxf_file, os.path.join(os.path.dirname(inputfile), outputfilebase + "_oda.dxf")) # complete target filename given
|
||||||
|
|
||||||
|
# Preprocessing DXF to DXF (entity filter) by using ezdxf the first time
|
||||||
if self.options.ezdxf_preprocessing:
|
if self.options.ezdxf_preprocessing:
|
||||||
# uniconverter does not handle all entities. we parse the file to exlude stuff which lets uniconverter fail
|
# uniconverter does not handle all entities. we parse the file to exlude stuff which lets uniconverter fail
|
||||||
dxf = ezdxf.readfile(dxf_file)
|
dxf = ezdxf.readfile(dxf_file)
|
||||||
@ -244,12 +255,14 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
shutil.copy2(dxf_file, os.path.join(os.path.dirname(inputfile), outputfilebase + "_ezdxf.dxf")) # complete target filename given
|
shutil.copy2(dxf_file, os.path.join(os.path.dirname(inputfile), outputfilebase + "_ezdxf.dxf")) # complete target filename given
|
||||||
|
|
||||||
# Make SVG from DXF
|
# Make SVG from DXF
|
||||||
if sys.platform != "win32":
|
if self.options.dxf_to_svg_parser == "sk1":
|
||||||
inkex.utils.debug("You selected sk1 UniConverter but you are not running on a Windows platform.")
|
if os.name != "nt":
|
||||||
|
inkex.utils.debug("You selected sk1 UniConvertor but you are not running on a Windows platform. On Linux uniconverter 1.1.X can be installed using the now obsolete Python 2.7, but it will not run correctly because you finally will fail at installing liblcms1-dev library on newer systems. That leads to uncompilable sk1libs package. Unfortunately sk1 UniConvertor 2.X does not support dxf format. So please use another DXF to SVG converter.")
|
||||||
|
exit(1)
|
||||||
sk1_command_ending = os.path.splitext(os.path.splitext(os.path.basename(self.options.sk1_uniconverter))[1])[0]
|
sk1_command_ending = os.path.splitext(os.path.splitext(os.path.basename(self.options.sk1_uniconverter))[1])[0]
|
||||||
if sk1_command_ending != ".cmd":
|
if sk1_command_ending != ".cmd":
|
||||||
inkex.utils.debug("You selected sk1 UniConverter but it was not configured properly. Check the path to the executable.")
|
inkex.utils.debug("You selected sk1 UniConverter but it was not configured properly. Check the path to the executable.")
|
||||||
elif self.options.dxf_to_svg_parser == "uniconverter":
|
exit(1)
|
||||||
uniconverter_cmd = [self.options.sk1_uniconverter, dxf_file, svg_file]
|
uniconverter_cmd = [self.options.sk1_uniconverter, dxf_file, svg_file]
|
||||||
#inkex.utils.debug(uniconverter_cmd)
|
#inkex.utils.debug(uniconverter_cmd)
|
||||||
proc = subprocess.Popen(uniconverter_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
proc = subprocess.Popen(uniconverter_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
||||||
@ -260,6 +273,10 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
subprocess.Popen(["explorer",temp_output_dir],close_fds=True)
|
subprocess.Popen(["explorer",temp_output_dir],close_fds=True)
|
||||||
|
|
||||||
elif self.options.dxf_to_svg_parser == "bjnortier":
|
elif self.options.dxf_to_svg_parser == "bjnortier":
|
||||||
|
if which("node") is None:
|
||||||
|
inkex.utils.debug("NodeJS executable not found on path. Please check your installation.")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
bjnortier_cmd = ["node", os.path.join("node_modules","dxf","lib","cli.js"), dxf_file, svg_file]
|
bjnortier_cmd = ["node", os.path.join("node_modules","dxf","lib","cli.js"), dxf_file, svg_file]
|
||||||
#inkex.utils.debug(bjnortier_cmd)
|
#inkex.utils.debug(bjnortier_cmd)
|
||||||
proc = subprocess.Popen(bjnortier_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
proc = subprocess.Popen(bjnortier_cmd, shell=False, stdout=PIPE, stderr=PIPE)
|
||||||
@ -298,7 +315,11 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Write the generated SVG into InkScape's canvas
|
# Write the generated SVG into InkScape's canvas
|
||||||
|
try:
|
||||||
stream = open(svg_file, 'r')
|
stream = open(svg_file, 'r')
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
inkex.utils.debug("There was no SVG output generated. Cannot continue")
|
||||||
|
exit(1)
|
||||||
p = etree.XMLParser(huge_tree=True)
|
p = etree.XMLParser(huge_tree=True)
|
||||||
doc = etree.parse(stream, parser=etree.XMLParser(huge_tree=True)).getroot()
|
doc = etree.parse(stream, parser=etree.XMLParser(huge_tree=True)).getroot()
|
||||||
stream.close()
|
stream.close()
|
||||||
@ -306,7 +327,7 @@ class DXFDWGImport(inkex.Effect):
|
|||||||
self.document.getroot().append(doc)
|
self.document.getroot().append(doc)
|
||||||
|
|
||||||
#get children of the doc and move them one group above - we don't do this for bjnortier tool because this has different structure which we don't want to disturb
|
#get children of the doc and move them one group above - we don't do this for bjnortier tool because this has different structure which we don't want to disturb
|
||||||
if self.options.dxf_to_svg_parser == "uniconverter":
|
if self.options.dxf_to_svg_parser == "sk1":
|
||||||
elements = []
|
elements = []
|
||||||
emptyGroup = None
|
emptyGroup = None
|
||||||
for firstGroup in doc.getchildren():
|
for firstGroup in doc.getchildren():
|
||||||
|
Reference in New Issue
Block a user