Let's talk about libredwg support
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
Be nice to others! Read the FreeCAD code of conduct!
Let's talk about libredwg support
We definetly need to support dwg-format via libredwg. libredwg now has python bindings.
Conda-forge now has packages for libredwg (linux/ osx) [1]. Releases for windows are also available [2]. But I am not sure if these are compatible with freecad. We also tried to create a conda-package for windows but failed with the mingw toolchain. There was one suggestion to use clang on windows to build libredwg [3]. I didn't try that yet, but this for sure is a possibility for the future.
@yorik
Can you briefly explain how to replace our current dwg-library (tigher?) with libredwg?
[1] https://github.com/conda-forge/libredwg-feedstock
[2] https://github.com/LibreDWG/libredwg/releases
[3] https://github.com/conda-forge/staged-r ... -496008470
Conda-forge now has packages for libredwg (linux/ osx) [1]. Releases for windows are also available [2]. But I am not sure if these are compatible with freecad. We also tried to create a conda-package for windows but failed with the mingw toolchain. There was one suggestion to use clang on windows to build libredwg [3]. I didn't try that yet, but this for sure is a possibility for the future.
@yorik
Can you briefly explain how to replace our current dwg-library (tigher?) with libredwg?
[1] https://github.com/conda-forge/libredwg-feedstock
[2] https://github.com/LibreDWG/libredwg/releases
[3] https://github.com/conda-forge/staged-r ... -496008470
Re: Let's talk about libredwg support
"TeighaConverter" is the old name, the new name is "ODAConverter".
Is libredwg a series of dynamically linked libraries, or does it provide an executable?
The current implementation in Draft/importDWG.py is that it searches for an executable defined in the parameter editor.
Code: Select all
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
p = p.GetString("TeighaFileConverter")
if p:
# path set manually
teigha = p
Code: Select all
teigha = "/usr/bin/TeighaFileConverter"
teigha = "/usr/bin/ODAFileConverter"
teigha = "TeighaFileConverter.exe"
Code: Select all
cmdline = ('"%s" "%s" "%s" "ACAD2000" "DXF" "0" "1" "%s"'
% (teigha, indir, outdir, basename))
...
subprocess.call(cmdline, shell=True)
Code: Select all
/usr/bin/ODAFileConverter indir outdir ACAD2000 DXF 0 1 filename.dwg
Code: Select all
dxf = convertToDxf(filename)
if dxf:
import importDXF
doc = importDXF.open(dxf)
return doc
Code: Select all
if dxfUseLegacyImporter:
processdxf(doc, filename)
return doc
else:
import Import
Import.readDXF(filename)
Therefore, libredwg could be used at different stages. If it includes an executable, it can be used instead of ODAConverter to convert to DXF, and then follow that path.
Code: Select all
if libredwg:
command = libreconvert
else:
command = ODAFileConverter
subprocess.call(command)
Code: Select all
if libredwg:
dxf = libredwg(filename, "DXF")
else:
# ODA or Teigha
dxf = convertToDxf(filename)
if dxf:
import importDXF
doc = importDXF.open(dxf)
return doc
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
Re: Let's talk about libredwg support
As far as I know, it's both: a c-library with python bindings and some executables for converting between different file formats (dxf, dwg, svg). So pretty generic. This are the executables which are included in the libredwg package:
Code: Select all
dwg2dxf dwg2SVG dwgbmp dwggrep dwglayers dwgread dwgrewrite dxf2dwg
Re: Let's talk about libredwg support
Something like this
Code: Select all
if libredwg:
command = "dwg2dxf"
dxf = subprocess.popen(command, filename)
# or if the program is available as a Python module
# dxf = libredwg.dwg2dxf(filename)
else:
# ODA or Teigha
dxf = convertToDxf(filename)
if dxf:
import importDXF
doc = importDXF.open(dxf)
return doc
Well, the legacy importer is made of 4 Python libraries, and I think it works okay, https://github.com/yorikvanhavre/Draft-dxf-importerAfterwards we might try to create a direct dwg importer by using the libredwg python interface (not sure if python is too slow for this task)
But I haven't tested with extremely large DXF files. As matter of fact, Draft will show a dialog when there are more than 1000 objects, maybe to warn the user, "this may take a while".
If you know of a test file that can be used to test many things, it would be nice to have it. There is currently no unit test in Draft to test DXF import and export, so just the slightest change can break the code, so it would be nice to have this unit test.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
Re: Let's talk about libredwg support
Yorik recommends the internal C++ importer for large files, like the BIM guys use. The legacy importer has more features though, bsplines for example (unless this has changed recently)
I think it's a good idea to add libredwg and leave ODA as your code suggests.
I will look at looo's links, hopefully the python bindings are pure python.
"fight the good fight"
Re: Let's talk about libredwg support
Yeah, I don't understand why it's called "legacy". It makes it sound old. It should just be called "Python importer", and "C++ importer". As you say, the Python importer may work better in some cases.
Yes, I think it would be good to keep the ODA option available for whoever wants it. Adding a new DWG importer shouldn't be a big problem, as long as it converts to DXF it should be fine.I think it's a good idea to add libredwg and leave ODA as your code suggests.
...
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
Re: Let's talk about libredwg support
First step was easy. But testing to export (to dwg) and import (from dwg) a circle created in freecad didn't work. But opening dwg's from libredwg/tests is working.
Here is the diff used so far:
Here is the diff used so far:
Code: Select all
diff --git a/src/Mod/Draft/importDWG.py b/src/Mod/Draft/importDWG.py
index bcc005770..ea619f02d 100644
--- a/src/Mod/Draft/importDWG.py
+++ b/src/Mod/Draft/importDWG.py
@@ -203,6 +203,17 @@ def convertToDxf(dwgfilename):
The new file produced.
"""
import os, tempfile, subprocess, sys
+
+ ############################ try libredwg
+ import shutil
+ if shutil.which("dwg2dxf"):
+ outdir = tempfile.mkdtemp()
+ basename = os.path.basename(dwgfilename)
+ result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
+ subprocess.call(("dwg2dxf", dwgfilename, "-o", result))
+ return result
+ ############################ end libredwg
+
teigha = getTeighaConverter()
if teigha:
indir = os.path.dirname(dwgfilename)
@@ -249,6 +260,14 @@ def convertToDwg(dxffilename, dwgfilename):
The same `dwgfilename` file path.
"""
import os, subprocess
+
+ ############################ try libredwg
+ import shutil
+ if shutil.which("dxf2dwg"):
+ subprocess.call(("dxf2dwg", dxffilename, "-o", dwgfilename))
+ return dwgfilename
+ ############################ end libredwg
+
teigha = getTeighaConverter()
if teigha:
indir = os.path.dirname(dxffilename)
Re: Let's talk about libredwg support
There is a comment in that file:
@looo doesn't it make sense to follow this advice ?
Code: Select all
# TODO: use subprocess.popen() instead of subprocess.call()
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Re: Let's talk about libredwg support
It's basically the same thing, subprocess.call() internally uses subprocess.Popen(). The latter is more low level, and provides more control over the communication with external programs. The call() function was used in older Python 2 code, so this shows that the code was written a while ago, but it should work the same in Python 3. I don't think it's very urgent to change the functions because the call to the external program is rather simple.
subprocess.Popen
subprocess.call
According to the documentation, for Python 3.5 and above, the recommendation is subprocess.run. Using this would completely break Python 2. Although we don't need to support Python 2, I think the best is to use Popen, because then it's available for every Python 3 version, not only for Python 3.5 and above.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.