这里写自定义目录标题
运用python基于北京公交线网txt数据绘制cad
文章前半部分为学习过程,后半部分为在cad中对北京市两千多条公交线路(单向)的绘制,先上效果图
导入pyautocad
pip install pyautocad
读取cad文件
from pyautocad import Autocad,APoint
import math
acad = Autocad(create_if_not_exists=True) #必须把cad文件打开
在cad控制台上打字
acad.prompt('hello world')
print(acad.doc.Name) #输出文件名
读取图层信息
layers_nums=acad.ActiveDocument.Layers.count #图层总数
print(layers_nums)
layers_names=[acad.ActiveDocument.Layers.Item(i).Name for i in range(layers_nums)] #图层名称
print(layers_names)
读取多段线顶点坐标
items=[]
for item in acad.iter_objects("PolyLine"):
print(item.Coordinates)
items.append(item.Coordinates)
print(len(items))
新建图层置为当前
layerobj=acad.ActiveDocument.Layers.Add('HIT_Layer')
acad.ActiveDocument.ActiveLayer=layerobj
cad上画图
#设置颜色
ClrNum=1
layerobj.color=ClrNum
# ClrNum为颜色索引号,其取值范围为[0,256];标准颜色的颜色索引号指定如下::1 红、2 黄、3 绿、4 青、5 蓝、6 洋红、7 白/黑; 0 ByBlock、256 ByLayer;
#画线l
p1=APoint(0,0) #所有点必须这样表示
p2=APoint(100,100)
acad.model.AddLine(p1,p2)
#画多段线pl
lon=[[55,66,77],[1,3,44],[755,74,1,20]]
lat=[[55,66,77],[1,3,44],[755,74,1,20]]
pnts=[]
for i in range(len(lon[2])):
pnts.append(APoint(lon[2][i],lat[2][i]))
pnts = np.array([j for i in pnts for j in i], dtype=np.float)
pnts = Autocad.aDouble(pnts)
pline_obj = acad.model.AddPolyLine(pnts)
#画图形
for i in range(5):
text = acad.model.AddText('Hi %s!' % i, p1, 2.5)
acad.model.AddLine(p1, p2)
acad.model.AddCircle(p1, 10)
p1.y += 10
dp = APoint(10, 0)
保存
acad.ActiveDocument.Application.preferences.OpenSave.AutoSaveInterval = 0.51
完整代码
from pyautocad import Autocad,APoint
import math
acad = Autocad(create_if_not_exists=True) #必须把cad文件打开
# acad.ActiveDocument.Application.Documents.Open("2.dwg")
#在cad控制台上打字
acad.prompt('hello world')
print(acad.doc.Name) #输出文件名
# # 使用SummaryInfo对象访问图纸的属性(只适用于Windows),也可以使用SummaryInfo访问自动定义属性
# for doc in acad.app.Documents:
# print(doc.Name) # 文件名
# print(doc.SummaryInfo.Author)
# print(doc.SummaryInfo.Comments)
# print(doc.SummaryInfo.HyperlinkBase)
# print(doc.SummaryInfo.Keywords)
# print(doc.SummaryInfo.LastSavedBy)
# print(doc.SummaryInfo.RevisionNumber)
# print(doc.SummaryInfo.Subject)
# print(doc.SummaryInfo.Title)
# 读取图层信息
layers_nums=acad.ActiveDocument.Layers.count #图层总数
print(layers_nums)
layers_names=[acad.ActiveDocument.Layers.Item(i).Name for i in range(layers_nums)] #图层名称
print(layers_names)
print(acad.ActiveDocument.Layers.Item(0))
# 读取多段线顶点坐标
items=[]
for item in acad.iter_objects("PolyLine"):
print(item.Coordinates)
items.append(item.Coordinates)
print(len(items))
#新建图层置为当前
layerobj=acad.ActiveDocument.Layers.Add('HIT_Layer')
acad.ActiveDocument.ActiveLayer=layerobj
#设置颜色
ClrNum=1
layerobj.color=ClrNum
# ClrNum为颜色索引号,其取值范围为[0,256];
# 标准颜色的颜色索引号指定如下::1 红、2 黄、3 绿、4 青、5 蓝、6 洋红、7 白/黑;
# 0 ByBlock、256 ByLayer;
#画线
p1=APoint(0,0) #所有点必须这样表示
p2=APoint(100,100)
acad.model.AddLine(p1,p2)
#画多段线
lon=[[55,66,77],[1,3,44],[755,74,1,20]]
lat=[[55,66,77],[1,3,44],[755,74,1,20]]
pnts=[]
for i in range(len(lon[2])):
pnts.append(APoint(lon[2][i],lat[2][i]))
pnts = np.array([j for i in pnts for j in i], dtype=np.float)
pnts = Autocad.aDouble(pnts)
# 将各点坐标顺序变换为行数据;
# 添加样条曲线时参数仅支持1行多列的1维数组,即将各点x,y,z坐标顺序排列构成的数组。
# 如报错可尝试增加该行代码 pnts = aDouble(pnts)
pline_obj = acad.model.AddPolyLine(pnts)
for i in range(5): #画图形
text = acad.model.AddText('Hi %s!' % i, p1, 2.5)
acad.model.AddLine(p1, p2)
acad.model.AddCircle(p1, 10)
p1.y += 10
dp = APoint(10, 0)
# 更改标注的位置
for text in acad.iter_objects('Text'):
print('text: %s at: %s' % (text.TextString, text.InsertionPoint))
text.InsertionPoint = APoint(text.InsertionPoint) + dp
for obj in acad.iter_objects(['Circle', 'Line']):
print(obj.ObjectName)
# text = acad.model.AddText("{0}".format(text), p1, 15) #添加文本,文本字符串,点的位置下显示文本,字体大小
# text.move(p1, p2) #文本從p1點移動到p2點
# acad.model.AddCircle(p1, 10) #画圆,圆心,半径
# acad.model.AddArc(p1, 500, math.radians(90), math.radians(270)) #画圆弧,圆心,半径,开始弧度,结束弧度
# 保存cad图到指定位置,第一個參數一定是保存的絕對路徑!!,64是保存的一種格式,筆者從1到100都試了一遍,
# 有一些是可以生成图的,都是CAD可以打開的文件類型格式。其實跟着筆者寫64就好!
# acad.doc.SaveAs("D:\\pycharm\\mycode\\this_pc_new\\dwg_read\\test.dwg", 64)
# acad.doc.SaveAs("{0}".format("D:\\pycharm\\mycode\\this_pc_new\\dwg_read\\test.dwg"), 64)
acad.ActiveDocument.Application.preferences.OpenSave.AutoSaveInterval = 0.51 #自动保存
将txt线条打印到cad中
遇到一个需求,统计北京市的所有公交线并置于cad中,目前有txt的文件,大概55.4m,这里放个字段的截图。
数据很大,不可能人工画,根据线路代码进行绘制,读取到一个新的线路代码就新建一个cad图层,直接上代码
from pyautocad import Autocad,APoint
import math
from tqdm import tqdm
from numba import jit
import numpy as np
#读取公交线路信息
s = []
code=[]
lon=[]
lat=[]
f= open('bus.txt','r')
for lines in f:
ls = lines.strip('\n').replace(' ','').replace('、','/').replace('?','').split('/')
for i in ls:
s.append(i)
f.close()
del s[0]
for i in s:
b = i.split(',', 2)
if b[0] not in code:
code.append(b[0])
lon.append([])
lat.append([])
lon[-1].append(b[1])
lat[-1].append(b[2])
# 高德火星坐标系转化为WGS84地理坐标系
def gcj2wgs(jingdu,weidu):
lon = float(jingdu)
lat = float(weidu)
a = 6378245.0 # 克拉索夫斯基椭球参数长半轴a
ee = 0.00669342162296594323 # 克拉索夫斯基椭球参数第一偏心率平方
PI = 3.14159265358979324 # 圆周率
# 以下为转换公式
x = lon - 105.0
y = lat - 35.0
# 经度
dLon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
dLon += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
dLon += (20.0 * math.sin(x * PI) + 40.0 * math.sin(x / 3.0 * PI)) * 2.0 / 3.0
dLon += (150.0 * math.sin(x / 12.0 * PI) + 300.0 * math.sin(x / 30.0 * PI)) * 2.0 / 3.0
# 纬度
dLat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))
dLat += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
dLat += (20.0 * math.sin(y * PI) + 40.0 * math.sin(y / 3.0 * PI)) * 2.0 / 3.0
dLat += (160.0 * math.sin(y / 12.0 * PI) + 320 * math.sin(y * PI / 30.0)) * 2.0 / 3.0
#转换
radLat = lat / 180.0 * PI
magic = math.sin(radLat)
magic = 1 - ee * magic * magic
sqrtMagic = math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * PI)
wgsLon = lon - dLon
wgsLat = lat - dLat
return wgsLon, wgsLat
# 度数坐标系转换成小数坐标系
def deg2flo(jingdu,weidu):
lon=str(jingdu)
lat=str(weidu)
flon=float(lon[:3])+float(lon[3:])/60
flat = float(lat[:2]) + float(lat[2:])/60
return flon,flat
# WGS84国际坐标系转GCJ02(火星坐标系)
def wgs2gcj(jingdu, weidu):
lon = float(jingdu)
lat = float(weidu)
a = 6378245.0 # 克拉索夫斯基椭球参数长半轴a
ee = 0.00669342162296594323 # 克拉索夫斯基椭球参数第一偏心率平方
PI = 3.14159265358979324 # 圆周率
# 以下为转换公式
x = lon - 105.0
y = lat - 35.0
# 经度
dLon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
dLon += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
dLon += (20.0 * math.sin(x * PI) + 40.0 * math.sin(x / 3.0 * PI)) * 2.0 / 3.0
dLon += (150.0 * math.sin(x / 12.0 * PI) + 300.0 * math.sin(x / 30.0 * PI)) * 2.0 / 3.0
# 纬度
dLat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))
dLat += (20.0 * math.sin(6.0 * x * PI) + 20.0 * math.sin(2.0 * x * PI)) * 2.0 / 3.0
dLat += (20.0 * math.sin(y * PI) + 40.0 * math.sin(y / 3.0 * PI)) * 2.0 / 3.0
dLat += (160.0 * math.sin(y / 12.0 * PI) + 320 * math.sin(y * PI / 30.0)) * 2.0 / 3.0
# 转换
radLat = lat / 180.0 * PI
magic = math.sin(radLat)
magic = 1 - ee * magic * magic
sqrtMagic = math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * PI)
wgsLon = lon + dLon
wgsLat = lat + dLat
return wgsLon, wgsLat
#画线
acad = Autocad(create_if_not_exists=True) #必须把cad文件打开
acad.ActiveDocument.Application.Documents.Open("aa.dwg")
for i in tqdm(range(len(code))): #公交线数量
layerobj = acad.ActiveDocument.Layers.Add(str(code[i])) # 新建图层置为当前 PolyLine
acad.ActiveDocument.ActiveLayer = layerobj
pnts = [] #多段线坐标转换
for j in range(len(lon[i])):
[wgsLon,wgsLat]=wgs2gcj(lon[i][j],lat[i][j]) #坐标转换
pnts.append(APoint(float(wgsLon)/5.8705*499.29, float(wgsLat)/6.3795*702.64))
# pnts.append(APoint(float(wgsLon), float(wgsLat)))
pnts = np.array([m for n in pnts for m in n], dtype=np.float)
pnts = Autocad.aDouble(pnts)
pline_obj = acad.model.AddPolyLine(pnts)
acad.ActiveDocument.Application.preferences.OpenSave.AutoSaveInterval = 0.51 #自动保存