python3读取autocad图形文件.py

'''
待完善。
此代码实现了,根据标注文本的
属性,数值,位置,及 容差,
去判断 设计 和 实测两图中的同一位置的尺寸。
如果是同一位置的尺寸,则进行比较,
并把结果存成表格,到运行此代码的当前目录。

此代码运行时,要读取的 dwg文件 必须处于打开状态。
且 不能在 移动(pan) 模式。

启动代码:
python dwg_measurements_comparison4.py [8]

其中,8代表,判定两图尺寸为同一尺寸的最大距离,
单位:米(图上单位)。自己决定具体是多少。

注意:
启动此代码后,首先要在cad软件中打开 对比图,
当该图读完后,提示切换到实测图时,请在cad软件中切换。
切换完成后,回车,即可。

包的安装:
pip install pyautocad
注:
1.该操作会自动安装 comtypes模块。
2.如要使用tables 命令,要另外安装xlrd 和 tablib
'''
from pyautocad import Autocad
import sys
from pyautocad.contrib.tables import Table
import re

acad = Autocad(create_if_not_exists=True)


def getDescription_Measurement_TextPositions():
    '''
    此函数用于读取 实测图 的尺寸标注的 属性,尺寸,尺寸位置。
    并返回结果。
    目前实测图带属性,对比图不带。
    '''
    print('正在读取 ', acad.doc.Name, ' ...')
    description_measurement_textPositions = []
    for obj in acad.iter_objects('Dimension'):
        description_measurement_textPositions.append(
            (obj.GetXData("MyDimDist")[1][1],
            round(obj.Measurement,2), 
            obj.TextPosition)
        )
    return description_measurement_textPositions


def getMeasurement_TextPositions():
    '''
    此函数用于读取 对比图 的尺寸,尺寸位置。
    并返回结果。
    '''
    print('正在读取 ', acad.doc.Name, ' ...')
    measurements_textPositions = []
    for a in acad.iter_objects('Dimension'):
        measurements_textPositions.append((round(a.Measurement,2), a.TextPosition))        
    return measurements_textPositions


def isTheSameMeasurement(point1,point2,tolerance):
    '''
    point1, 类似这样(82.37, (81953.97462829649, 276686.2885731713, 0.0)),
    82.37,代表标注的尺寸,后边代表,该尺寸在图上显示的位置坐标。
    point2, 类似这样('车间二;长', 82.44, (81951.56923143109, 276679.7827104012, 0.0))
    
    此函数通过 两个标注的距离来判断,
    两个尺寸,是否是同一位置处的尺寸。
    是,return True
    否,return False

    tolerance,设计/实测图的同一位置两个尺寸标注允许的距离差。
    即,在这个距离差之内,认为是同一个对象的尺寸,可以进行比对。
    '''    
    p1x = point1[1][0]
    p1y = point1[1][1]
    p2x = point2[2][0]
    p2y = point2[2][1]
    d = ((p1x - p2x) ** 2 + (p1y - p2y) ** 2) ** 0.5
    if d < tolerance:
        return True
    else:
        return False


def handleData(lst):
    '''
    此函数用于处理读取到的原始数据,
    把原始数据分成三类:
    长,宽,间距 三个列表如下:
    lengthLst,widthLst,distanceLst,
    并返回。
    '''
    lengthLst = []
    widthLst = []
    distanceLst = []
    for i in lst:
        key = i[0].split(';')[1]
        if key == '间距':
            distanceLst.append(i)
        elif key == '长':
            lengthLst.append(i)
        elif key == '宽':
            widthLst.append(i)
    return lengthLst,widthLst,distanceLst


def handleLengthWidth(lengthLst,widthLst):
    '''
    此函数用于处理长度列表和宽度列表,
    组合成一个列表,即报告中需要的数据结构。

    其中,连廊只有宽度,需单独处理。
    '''
    tableContents = []
    tableName = '竣工建(构)筑物满外尺寸对比表'
    tableHead = ['\\', '发证长度', '实测长度', '长度差值(允许误差值)',
        '发证宽度', '实测宽度', '宽度差值(允许误差值)'        
    ]
    tableContents.append(tableHead)
    # 处理连廊尺寸。
    for w in widthLst:
        keyW = w[0].split(';')[0]
        if re.match('连廊', keyW):
            w2 = [keyW]
            w2.extend(['---','---','---'])
            w2.extend(w[1:])
            tableContents.append(w2)
    # 处理同时有长宽的尺寸。
    for l in lengthLst:
        keyL = l[0].split(';')[0]
        for w in widthLst:
            keyW = w[0].split(';')[0]            
            if keyL == keyW:
                w2 = w[1:]
                l[0] = l[0].split(';')[0]
                l.extend(w2)
                tableContents.append(l)
                break
    tableContents.sort()
    return tableName,tableContents


def handleDistance(distanceLst):
    '''
    此函数用于处理建筑物 间距尺寸。    
    '''
    tableContents = []
    tableName = '竣工建(构)筑物间距对比表'
    tableHead = [
        '\\', '发证间距', '实测间距', 
        '差值', '允许误差值'
    ]
    tableContents.append(tableHead)
    for dl in distanceLst:
        dl[0] = dl[0][:-3]
        new = dl[-1][6:-1]
        dl[-1] = dl[-1][:5]
        dl.append(new)
        tableContents.append(dl)
    tableContents.sort()
    return tableName,tableContents


def handleDJ():
    '''
    此函数用于处理地界特征点。
    '''
    tableContents = []
    tableName = '用地界址坐标表'
    tableHead = [
        '点号', 'X坐标(米)', 'Y坐标(米)'
    ]
    tableContents.append(tableHead)
    area = 0
    for obj in acad.iter_objects("PolyLine"):
        if obj.Layer == 'DJHX':
            area = '%.1f' % obj.Area
            t = obj.Coordinates
            if 0 in t:
                DJHX = [('%.3f' % t[i], '%.3f' % t[i+1], t[i+2]) for i in range(0,len(t),3)]
            else:
                DJHX = [('%.3f' % t[i], '%.3f' % t[i+1], 0) for i in range(0,len(t),2)]
            break
    for i in range(len(DJHX)):
        tableContents.append(['J' + str(i + 1), DJHX[i][1], DJHX[i][0]])
    tableContents.append(['用地面积', area, '平方米'])
    return tableName,tableContents
        

def write_to_table(tableName,tableContents):
    table = Table()
    for row in tableContents:
        table.writerow(row)
    table.save(tableName + '.xls', 'xls')


def main(tolerance):
    i = input('请在CAD软件中打开 对比图。打开了吗?[Y]')
    if i == '' or i.upper() == 'Y':
        # dmt1, 第一次读取的尺寸, 设计尺寸。
        dmt1 = getMeasurement_TextPositions()
        print('此图有效尺寸数:', len(dmt1), ' 个')
        # print(dmt1)
        print()
    i = input('请在CAD软件中切换到 实测图。切换了吗?[Y]')
    if i == '' or i.upper() == 'Y':
        # dmt2, 第二次读取的尺寸,实测尺寸。
        dmt2 = getDescription_Measurement_TextPositions()
        print('此图有效尺寸数:', len(dmt2), ' 个')
        # print(dmt2)
        print()
    # print(dmt1,dmt2,sep='\n\n')
    # d_value, 存储两个同位置尺寸的 属性,设计尺寸,实测尺寸,及差值。
    d_value = []
    for m1 in dmt1:
        for m2 in dmt2:
            if isTheSameMeasurement(m1,m2,tolerance):
                d_value.append([
                    m2[0],'%.2f' % m1[0],'%.2f' % m2[1], 
                    '%.2f' % (m2[1] - m1[0]) + '(±' + '%.2f' % (m1[0] * 0.005) + ')'
                ])
                break
    print('比对两图尺寸数:', len(d_value), ' 个')
    print('两图中判定为同一尺寸的容差:', tolerance, ' 米(图上单位)。')    

    lengthLst,widthLst,distanceLst = handleData(d_value)
    # print(lengthLst,widthLst,distanceLst,sep='\n')
    tableName,tableContents = handleLengthWidth(lengthLst,widthLst)
    print()
    print(tableName)
    write_to_table(tableName,tableContents)

    tableName,tableContents = handleDistance(distanceLst)
    print(tableName)
    write_to_table(tableName,tableContents)

    tableName,tableContents = handleDJ()
    print(tableName)
    write_to_table(tableName,tableContents)


if __name__ == '__main__':
    try:
        tolerance = sys.argv[1]
        main(int(tolerance))
    except IndexError:
        # 默认两图尺寸相差2米内算同一个尺寸。
        main(2)
 

你可能感兴趣的:(pyautocad)