加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

使用python将cad批量导出至pdf

(2014-07-06 03:35:16)

脚本用于将cad中的标准图框逐个导出成pdf文件(单个文件而不是多个文件)。并且要求按照从左至右,从上至下的顺序来导出文件。

------------------------------------------------------------------------------------------------------------------------------------

需要进行导出cad文件的截图

http://hiphotos.baidu.com/dengsilou/pic/item/bd7fa344aae61dedb3b7dc87.jpg

-------------------------------------------------------------------------------------------------------------------------------------

实践中,最初使用autocad的VBA,不过最初的方法没有考虑到图框输出的顺序。由于需要考虑顺序于是转用python,使用win32com组件难以写入坐标,因此改用comtypes模块。使用comtypes来处理的麻烦在于ms.Item(i)获取的接口与VBA的不同(像VBA那样ms.Item(i).Lengh会报错),VBA和其他程序中使用接口的差别不是特别了解,只是知道在获取接口之后必须通过接口查询来获取需要的另外接口,程序中为了获取多段线的长度Length而必须更换接口。另外向CAD传递坐标需要使用到array模块。

几处关键所在:

1.需要安装comtypes模块与pdfFactory虚拟打印机。

2.需要接口查询获取需要的接口。

3.对于搜索的图框进行排序,纵轴方向降序而横轴升序。

4.对于搜索到的图框,考虑到是横向还是纵向。

注意的问题:

1.各个图框绘制时并非都是左上角对齐到网格,因此需要处理。frames.sort(lambda x,y:(cmp(round(y[0][1]/20,0),round(x[0][1]/20,0)) or cmp(round(x[0][0]/20,0),round(y[0][0]/20,0))))虽然在大多时候会得到正确的结果,但极端状况下图框的顺序还是会有些错误。无论用int也好round也好,效果都差不多。

2.在python对于一些对象值的设定需要在VBA对象浏览器中查询,比如在VBA中使用layout.PaperUnits = acMillimeters,而在python中必须使用layout.PaperUnits = 1。

3.打印时候需要设置前台打印,否则可能报错,doc.SetVariable('BACKGROUNDPLOT', 0)。

4.对于打印输出的相关设置最好显示给值,而不使用适用默认值,因为很多CAD文档会有一些意想不到的设置。

5.使用VBA是很直接的一种方式,如果改用python而没有体现python的优势,还是保持VBA的为好。使用python往往是需要使用一些特定的模块,或是特定构造有关,如lis,dict等。

-------------------------------------------------------------------------------------------------------------------------------------

# -*- coding: utf-8 -*-
'''
Created on 2011-9-20
@author: mtl
'''

import array
import comtypes.client

#根据需要修改以下参数。
paper = 'A3'

def main():
    #打印机设置。
    acad = comtypes.client.GetActiveObject("AutoCAD.Application")
    doc = acad.ActiveDocument
    ms = doc.ModelSpace
   doc.ActiveLayout.ConfigName = "pdfFactory Pro"
    if paper == 'A3':
        doc.ActiveLayout.CanonicalMediaName = "A3"
        perimeter = 1434
    elif paper == 'A4':
        doc.ActiveLayout.CanonicalMediaName = "A4"
        perimeter = 1014
    doc.ActiveLayout.PaperUnits = 1
    
    doc.ActiveLayout.CenterPlot = True
    doc.Plot.QuietErrorMode = False
    doc.ActiveLayout.UseStandardScale = False
    doc.ActiveLayout.SetCustomScale(1, 1)
    doc.SetVariable('BACKGROUNDPLOT', 0)
    doc.Regen(1)

    #搜索所有标准图框。
    frames = []
    for i in range(0,ms.Count):
        if ms.Item(i).ObjectName == 'AcDbPolyline':
            pline = ms.Item(i).QueryIn
更多来源:http://www.zgjx114.com/question/
terface(comtypes.gen.AutoCAD.IAcadLWPolyline)
            if abs(pline.Length - perimeter) < 2:
                ll,ur = pline.GetBoundingBox()
                print ll,ur
                frames.append([(ll[0],ur[1]),ll[:-1],ur[:-1]])

    #图框排序:y轴降序,x轴升序。
    frames.sort(lambda x,y:(cmp(round(y[0][1]/20,0),round(x[0][1]/20,0)) or cmp(round(x[0][0]/20,0),round(y[0][0]/20,0))))
    
    #打印输出。
    for frame in frames:
        #设定横向/纵向打印。
        if abs(frame[1][0] - frame[2][0]) > abs(frame[1][1] - frame[2][1]):
            doc.ActiveLayout.PlotRotation = 1
        else:
            doc.ActiveLayout.PlotRotation = 0
        doc.ActiveLayout.SetWindowToPlot(array.array('d',frame[1]), array.array('d',frame[2]))
        doc.ActiveLayout.PlotType = 4
        doc.Plot.PlotToDevice(doc.ActiveLayout.ConfigName)

if __name__ == "__main__":
    main()

0

阅读 收藏 喜欢 打印举报/Report
前一篇:祝福
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有