方法一Github
这个是ezdxf出品的,可以使用命令行的方式进行转换
bash
ezdxf draw -o file.<png|svg|pdf> <file.dxf>
也可以自己改动代码
examples/addons/drawing/pdf_export.py
但是直接运行会有误,以下是我改动后的代码:
python
from ezdxf.addons import odafc
import ezdxf
import os
import json
import re
import pathlib
import time
from ezdxf.addons.drawing import Frontend, RenderContext
from ezdxf.addons.drawing import pymupdf, layout
def transparency(filepath):
doc = ezdxf.readfile(filepath)
msp = doc.modelspace()
backend = pymupdf.PyMuPdfBackend()
Frontend(RenderContext(doc), backend).draw_layout(msp)
pdf_bytes = backend.get_pdf_bytes(
layout.Page(0, 0, layout.Units.mm), settings=layout.Settings(scale=10)
)
pdf_file = os.path.join(os.path.dirname(filepath), os.path.basename(filepath).split(".")[0] + "_dwg.pdf")
(pathlib.Path(pdf_file)).write_bytes(pdf_bytes)
def export(filepath: pathlib.Path, layout_names=("Model",), scale=1):
print(f"\nprocessing: {filepath.name}")
t0 = time.perf_counter()
doc = ezdxf.readfile(filepath)
t1 = time.perf_counter()
print(f"loading time: {t1 - t0: .3f} seconds")
for layout_name in layout_names:
outname = filepath.stem + f"-[{layout_name}]" + ".pdf"
CWD = os.path.dirname(filepath)
outname = pathlib.Path(CWD+"/"+outname)
print(outname)
t1 = time.perf_counter()
if layout_name == "Model":
dxf_layout = doc.modelspace()
page = layout.Page(
0, # auto-detect
0, # auto-detect
layout.Units.mm, # 1 drawing unit = 1mm
layout.Margins.all(0),
max_width=1189, # limit page width to 1189mm
max_height=841, # limit page height to 841mm
)
settings = layout.Settings(scale=scale)
else:
try:
dxf_layout = doc.paperspace(layout_name)
except KeyError:
print(f"Layout '{layout_name}' not found")
continue
page = layout.Page.from_dxf_layout(dxf_layout)
settings = layout.Settings(
fit_page=False,
scale=dxf_layout.get_plot_unit_scale_factor() * scale,
)
backend = pymupdf.PyMuPdfBackend()
# You can get the content bounding box in DXF drawing units, before you create the
# PDF output to calculate page size, margins, scaling factor and so on ...
# content_extents = backend.bbox()
Frontend(RenderContext(doc), backend).draw_layout(dxf_layout)
pdf_bytes = backend.get_pdf_bytes(page, settings=settings)
t2 = time.perf_counter()
print(f"render time: {t2 - t1: .3f} seconds")
(outname).write_bytes(pdf_bytes)
class dwg_analysis:
def __init__(self, filepath, format):
self.filepath = filepath
self.format = format
def dwg2data(self):
dxf_file = os.path.join(os.path.dirname(self.filepath), os.path.basename(self.filepath).split(".")[0] + ".dxf")
odafc.convert(self.filepath, dxf_file, version='R2000', replace=True)
doc = ezdxf.readfile(dxf_file)
msp = doc.modelspace()
pdf_file = export(pathlib.Path(dxf_file),["Model", "PLAN", "SECTION"],)
# pdf_file = transparency(dxf_file)
data = {}
# 获取TEXT实体
texts = msp.query('TEXT')
text_data = []
if self.format == "dwg_text":
for text in texts:
decoded_str = re.sub(r'\\U\+([0-9A-Fa-f]{4})', lambda m: chr(int(m.group(1), 16)), text.dxf.text)
text_data.append(decoded_str)
filtered_list = [item for item in text_data if not (isinstance(item, (int, float)) or (isinstance(item, str) and str.isdigit(item)) or (isinstance(item, str) and item.isdigit()))]
data['document'] = self.remove_duplicates(filtered_list)
data['metadata'] = pdf_file
data['format'] = format
return data
for text in texts:
decoded_str = re.sub(r'\\U\+([0-9A-Fa-f]{4})', lambda m: chr(int(m.group(1), 16)), text.dxf.text)
text_info = {
'text': decoded_str,
'insert': (text.dxf.insert[0], text.dxf.insert[1]),
'height': text.dxf.height,
'rotation': text.dxf.rotation,
'style': text.dxf.style,
'layer': text.dxf.layer
}
text_data.append(text_info)
data['TEXT'] = text_data
# 获取LINE实体
lines = msp.query('LINE')
line_data = []
for line in lines:
line_data.append({
'start': (line.dxf.start[0], line.dxf.start[1]),
'end': (line.dxf.end[0], line.dxf.end[1])
})
data['LINE'] = line_data
# 获取POLYLINE实体
polylines = msp.query('POLYLINE')
polyline_data = []
for polyline in polylines:
points = []
for point in polyline.points():
points.append((point[0], point[1]))
polyline_data.append(points)
data['POLYLINE'] = polyline_data
# 获取CIRCLE实体
circles = msp.query('CIRCLE')
circle_data = []
for circle in circles:
circle_data.append({
'center': (circle.dxf.center[0], circle.dxf.center[1]),
'radius': circle.dxf.radius
})
data['CIRCLE'] = circle_data
# 获取ARC实体
arcs = msp.query('ARC')
arc_data = []
for arc in arcs:
arc_data.append({
'center': (arc.dxf.center[0], arc.dxf.center[1]),
'radius': arc.dxf.radius,
'start_angle': arc.dxf.start_angle,
'end_angle': arc.dxf.end_angle
})
data['ARC'] = arc_data
# 获取ELLIPSE实体
ellipses = msp.query('ELLIPSE')
ellipse_data = []
for ellipse in ellipses:
ellipse_data.append({
'center': (ellipse.dxf.center[0], ellipse.dxf.center[1]),
'major_axis': (ellipse.dxf.major_axis[0], ellipse.dxf.major_axis[1]),
'ratio': ellipse.dxf.ratio,
'start_param': ellipse.dxf.start_param,
'end_param': ellipse.dxf.end_param
})
data['ELLIPSE'] = ellipse_data
return data
def remove_duplicates(self,lst):
res = []
seen = {}
for i in lst:
if i not in seen:
seen[i] = 1
res.append(i)
return res
# 示例调用
if __name__ == "__main__":
# DWG文件路径
DWG_path = "/home/hyh/data/Maintenance_test_data/AIN.dwg"
format = "dwg_text"
dwf = dwg_analysis(DWG_path,format)
dwf_txt = dwf.dwg2data()
output_path = os.path.join(os.path.dirname(DWG_path), os.path.basename(DWG_path).split(".")[0] + "_" +format+ ".json")
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(dwf_txt, f, ensure_ascii=False, indent=4)
方法二Github
一位国内大神出品的项目
🆒 cad2x @orcastor-previewer
预编译版本: 字体与图案 (3.53MB) | linux_arm64 (2.88MB) | linux_x64 (3.42MB) | win_x64 (3.61MB)
cad2x
- 一个最小化的单文件命令行工具,用于将 CAD 文件(DXF / DWG)转换为其他格式(DXF / PDF / PNG / SVG),衍生自 LibreCAD (commit: 0601535)。
特性
- 💼 便携 - 无图形界面 & 无依赖项
- 🌈 定制 - 大幅精简了
Qt 5.12.12
(QtCore
&QtGUI
) - 🚀 极小 - 2.9MB 的二进制文件大小(在
aarch64-linux
平台上) - � 显示 - 支持显示格式错误的 Unicode 字符 - DXF 文件编码
- 🗳️ 跨平台 - 支持 MacOS、Windows、Linux、安卓、iOS和大多数基于Linux的操作系统
- 🔠 重用 - 懒加载
ttf
/ttc
TrueType 字体(不仅限于lff
/cxf
)- 以较少的开销共享系统和其他应用程序的字体
最佳实践
sh
使用方法: ./cad2x [选项] <dxf/dwg 文件>
将 DXF/DWG 文件转换为 DXF v2007/PDF/PNG/SVG 文件。
示例:
cad2x *.dxf|*.dwg|*
-- 将所有 dxf/dwg 文件打印为具有相同文件名的 pdf 文件。
cad2x -o svg *.dxf|*.dwg|*
-- 将所有 dxf/dwg 文件转换为 svg 格式。
cad2x -o b.png a.dwg
-- 将 a.dwg 文件打印为 b.png。
选项:
-h, --help 显示此帮助。
-v, --version 显示版本信息。
-a, --auto-orientation 根据文档边界框自动设置纸张方向(横向或纵向)。
-b, --monochrome 打印单色(黑/白)。
-c, --fit 自动适应并居中绘图到页面。
-e, --code-page <codepage> 设置默认的代码页(默认为 ANSI_1252)。
-f, --default-font <font> 设置默认字体(默认为 standard)。
-l, --font-dirs <dir1,dir2,dir3...> 设置更多字体目录。
-m, --margins <L,T,R,B> 页面边距(毫米)(整数或浮点数)。
-n, --pages <HxV> 在多页上打印(水平 x 垂直)。
-o, --outfile <file> 输出 DXF v2007/PDF/PNG/SVG 文件。
-p, --paper <WxH> 页面尺寸(宽 x 高)(毫米)。
-r, --resolution <integer> 输出分辨率(DPI)。
-s, --scale <double> 输出比例。例如:0.01(表示 1:100 比例)。
-t, --directory <path> 目标输出目录。
参数:
<dxf/dwg 文件> 输入 DXF/DWG 文件(们)
将所有 dwg
文件转换为 pdf
格式
- 检测方向 (-a)
- 自动适应并居中绘图到页面 (-c)
- 到
output
目录 (-t)
./cad2x -o pdf *.dwg -t output -ac
将 a.dxf
转换为 b.png
- 检测方向 (-a)
- 自动适应并居中绘图到页面 (-c)
- 将页面大小设置为 2970 x 2100 (-p 2970x2100)
- 设置边距 (-m 2.0,2.0,2.0,2.0)
./cad2x -o b.png a.dxf -ac -p 2970x2100 -m 2.0,2.0,2.0,2.0
将 a.dwg
转换为 b.dxf
(v2007)
./cad2x -o b.dxf a.dwg
将 a.dxf
(QCad / v2004 / v2000 / v14 / v12)转换为 b.dxf
(v2007)
./cad2x -o b.dxf a.dxf
将 a.dxf
转换为 b.pdf
- 检测方向 (-a)
- 自动适应并居中绘图到页面 (-c)
- 设置默认代码页为中文 (-e ANSI_936)
- 设置默认字体 (-f simsun)
- 添加字体列表 (-l /one/fonts,/two/fonts)
./cad2x -o b.pdf a.dxf -e ANSI_936 -f simsun -ac -l /one/fonts,/two/fonts
代码页参考
语言 | DXF 代码页 |
---|---|
泰语 | ANSI_874 |
日语 | ANSI_932 |
简体中文 | ANSI_936 |
韩语 | ANSI_949 |
繁体中文 | ANSI_950 |
中欧 | ANSI_1250 |
西里尔语 | ANSI_1251 |
西欧 | ANSI_1252 |
希腊语 | ANSI_1253 |
土耳其语 | ANSI_1254 |
希伯来语 | ANSI_1255 |
阿拉伯语 | ANSI_1256 |
波罗的海语 | ANSI_1257 |
越南语 | ANSI_1258 |
Linux构建教程
准备
sh
apt update
apt-get install g++ gcc make git-core pkg-config qt5-qmake libfreetype-dev -y --no-install-recommends
构建精简版的 qtbase(Qt 5.12.12)
- [强烈推荐] 静态 QtCore & QtGUI 库
sh
cd ./3rdparty/qtbase/
./configure -developer-build -release -no-iconv -no-icu -static -strip -confirm-license -opensource
qmake -qt=qt5 -r -- -developer-build -release -no-iconv -no-icu -static -strip -confirm-license -opensource
make -j20
cd src/corelib
make install_targ_headers
make -j20 staticlib
cd ../gui
make install_targ_headers
make -j20 staticlib
- [可用备选方案] 共享 QtCore & QtGUI 库
sh
cd ./3rdparty/qtbase/
./configure -developer-build -release -no-iconv -no-icu -strip -confirm-license -opensource -R .
qmake -qt=qt5 -r -- -developer-build -release -no-iconv -no-icu -strip -confirm-license -opensource -R .
make -j20
make install
构建 cad2x
sh
qmake -qt=qt5 -r
make -j20
Windows(x64)构建教程
准备
-
安装Qt 5.12.12 for windows,勾选
MinGW7.3.0
-
下载MinGW7.3.0-seh,解压到磁盘某个位置,比如
D:\mingw64
-
设置
D:\mingw64\bin
、D:\mingw64\x86_64-w64-mingw32\bin
、D:\mingw64\libexec\gcc\x86_64-w64-mingw32\7.3.0
到系统环境变量Path
-
把
D:\mingw64\bin\mingw32-make
修改成make
-
从
./3rdparty/qtbase/
替换$QT$\Qt5.12.12\5.12.12\mingw73_64
目录下的include
和mkspecs
文件夹
构建精简版的 qtbase(Qt 5.12.12)
-
通过开始菜单的
Qt 5.12.12 (MinGW 7.3.0 64-bit)
进入cmd
(命令提示符) -
静态 QtCore & QtGUI 库
sh
cd ./3rdparty/qtbase/
configure -developer-build -release -platform win32-g++ -no-iconv -no-icu -static -strip -confirm-license -opensource -qt-zlib -qt-freetype
qmake -r -- -developer-build -release -platform win32-g++ -no-iconv -no-icu -static -strip -confirm-license -opensource -qt-zlib -qt-freetype
make -j20
构建 cad2x
sh
qmake -r
make -j20
使用upx进行压缩
sh
./upx -9 --ultra-brute cad2x
更改日志
-
✨ 通过简单拖放添加字体到
cad2x-converter/output/fonts
-
✂️ 裁剪QtBase
- ✂️ 裁剪 QtWidgets & QtPrintSupport 依赖项
- ✂️ 裁剪 GUI 应用程序的依赖项(QtGuiApplication / accessible / input / events / plugins)
- ✂️ 裁剪 Render 的依赖项(OpenGL / Vulkan / KMS / VNC)
- ✂️ 裁剪 qpa 的依赖项(X 服务器等)
- ✂️ 裁剪 ICU / PCRE2 的依赖项
- ✂️ 裁剪无用代码(Pixmap / Icon / Windows 等)
- ✂️ 内置字体数据库,无需插件
-
✂️ 摘选出关键代码
-
✂️ 裁剪 boost 的依赖项
-
✂️ 最小的二进制文件大小(静态链接)(在
strip
和upx -9 --ultra-brute
之后为 2.9MB)sh> ldd cad2pdf libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x00000055021dc000) libglib-2.0.so.0 => /lib/aarch64-linux-gnu/libglib-2.0.so.0 (0x00000055021f0000) libpng16.so.16 => /lib/aarch64-linux-gnu/libpng16.so.16 (0x000000550232b000) libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x000000550236f000) libfreetype.so.6 => /lib/aarch64-linux-gnu/libfreetype.so.6 (0x000000550241a000) libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x00000055024d9000) libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x000000550256b000) libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x000000550259c000) libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000005502781000) libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000055027a5000) /lib/ld-linux-aarch64.so.1 (0x0000005500000000) libpcre.so.3 => /lib/aarch64-linux-gnu/libpcre.so.3 (0x0000005502918000)
-
✂️ 合并: cad2pdf + cad2pic = cad2x
-
🛠️ 修复: png 大小自动设置
-
🛠️ 修复: 输出文件参数
-
🛠️ 修复: 格式错误的 Unicode 字符 - DXF 文件编码
-
🛠️ 修复: QCad 格式 DXF 中实体的不正确偏移
-
🆕 功能: 支持自动方向检测
-
🆕 功能: 懒加载
ttf
/ttc
字体文件支持(不仅限于lff
/cxf
) -
🆕 功能: 自动设置系统字体目录
- -
C:\Windows\Fonts
- -
/Library/Fonts
/System/Library/Fonts
- -
/usr/share/fonts
/usr/local/share/fonts
~/.fonts
- -
-
🆕 功能: 支持更多导出格式
- 从 DWG 到 BMP 缩略图的快速方式
- DWG / DXF 到 JSON 用于 cad.js
- DWG / DXF 到 XML
- DWG / DXF 到 TXT
-
🆕 功能: 支持3D模型文件
参考
您可以首先参考原始的 LibreCAD Wiki - 从源代码构建 页面。
常见问题解答
问: 如何导出其他图像格式,如 bmp / jpeg / tiff / ico / tga?
答: 创建一个名为 'plugins/imageformats' 的目录,并将
libq<fmt>.so
/q<fmt>.dll
放入其中(可以从 这里 找到,<fmt>为具体格式),应用程序将自动加载插件。
问:如果导出的文件空白怎么办?
答:3D模型暂时不支持,如果不是3D文件,尝试添加
-c
参数导出。
问:如果出现乱码怎么办?
答:尝试添加默认编码和对应字体尝试,比如
-e ANSI_936 -f simsun
,设置默认简体中文,默认字体为宋体。