需求:在项目中甲方的测绘图纸很多是用cad进行存储,希望能有一个功能对cad文件坐标信息进行提取并绘制在前端与相关图层叠加等
难点:先前找了一些java的开源cad读取库但都对cad的版本支持不全,且有些已经很久无维护,后面采用了arcgis的arcpy进行dwg文件处理解析成geojson,虽然依赖于arcgis但对dwg版本支持全面。
代码: python:主要思路是读取cad文件,并传入对应的dwg文件路径和dwg坐标系以及你想输出的坐标系.其中涉及坐标定义,坐标转换,cad色号转换,dwg属性过滤,最终geojson生成的路径可以固定也可以用输入参数控制。
# coding=utf-8
import arcpy
import sys
import json
reload(sys)
sys.setdefaultencoding('utf-8')
# 默认覆盖
arcpy.env.overwriteOutput = True
dwg_spatial = None
out_spatial = None
filterArr = ["村界线","涵管","沟","渠","道","路","桥","水","地块","槽"]
def contains_item_fuzzy(char_to_find):
return any(item in char_to_find for item in filterArr)
def tranformPolygon(arr):
array = arcpy.Array([arcpy.Point(*coords) for coords in arr])
fs = arcpy.Polygon(array, dwg_spatial)
js = fs.projectAs(out_spatial)
return js.JSON
def tranformPolyLine(arr):
array = arcpy.Array([arcpy.Point(*coords) for coords in arr])
fs = arcpy.Polyline(array, dwg_spatial)
js = fs.projectAs(out_spatial)
return js.JSON
def getColorFromCad(type):
if type == 1:
return "rgb(255 0 0)"
if type == 2:
return "rgb(255 255 0)"
if type == 3:
return "rgb(0 255 255)"
if type == 4 or type == 151: #范围线 沟渠
return "rgb(0 255 255)"
if type == 5:
return "rgb(0 0 255)"
if type == 6:
return "rgb(255 0 255)"
if type == 7 or type == -2: #村界线
return "rgb(0 0 0)" #黑色
if type == 8:
return "rgb(128 128 128)"
if type == 9:
return "rgb(192 192 192)"
if type == 10:
return "rgb(255 0 0)"
if type == 11:
return "rgb(255 127 127)"
if type == 15:
return "rgb(153 76 76)"
if type == 131:
return "rgb(153 76 76)"
if type == 154:
return "rgb(0 76 153)"
return None
def cadToJson(filePath):
try:
# 加载dwg数据
arcpy.env.workspace = filePath
layers = arcpy.ListFeatureClasses()
datas = {
"type": "FeatureCollection",
"features": []
}
for fc in layers:
if fc == "Polyline" or fc == "Polygon":
with arcpy.da.SearchCursor(fc, ["SHAPE@JSON", "Layer", "Color"], "", dwg_spatial) as cursor:
for row in cursor:
bool = fc == "Polygon"
isColor = getColorFromCad(row[2])
if row[0] is not None and isColor is not None and contains_item_fuzzy(row[1]) :
geom = {
"type":"Feature",
"properties":{
"name": row[1],
"color": getColorFromCad(row[2])
},
"geometry":{
"type":"",
"coordinates":""
},
}
if bool:
geom["geometry"]['type'] = "Polygon"
geom["geometry"]['coordinates'] = [eval(tranformPolygon(eval(row[0])["rings"][0]))["rings"][0]]
datas.get('features').append(geom)
else:
geom["geometry"]['type'] = "LineString"
geom["geometry"]['coordinates'] = eval(tranformPolyLine(eval(row[0])["paths"][0]))["paths"][0]
datas.get('features').append(geom)
# 将数据保存到json文件
with open('E:\work\git\cadServices/cads/data.json', 'w') as json_file:
json.dump(datas, json_file)
print ("success")
except Exception as err:
print("error")
if __name__ == '__main__':
try:
arg1 = sys.argv[1] # dwg文件路径
arg2 = sys.argv[2] # dwg文件坐标系
arg3 = sys.argv[3] # 输出坐标系
if arg2 :
arg2 = int(arg2)
if arg3 :
arg3 = int(arg3)
dwg_spatial = arcpy.SpatialReference(arg2 or 4526)
out_spatial = arcpy.SpatialReference(arg3 or 4490)
if arg1:
cadToJson(arg1)
except Exception as err:
print ("请传必须参数", err)
java代码片段: 采用springboot框架,获取dwg文件,并调用写的python进行处理获取返回geojson。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.cadservices.untils.ResponseModel;
import java.io.*;
@Service
public class CadServices {
@Value("${python.env_path}")
private String pythonEnvPath;
@Value("${python.code_path}")
private String pythonCodePath;
@Value("${dwg_spatial}")
private String dwgSpatial;
@Value("${out_spatial}")
private String outSpatial;
//默认保存在当前项目下
private String workPath = System.getProperty("user.dir")+"/cads/";
//cad解析成json
public ResponseModel getCadToJson(MultipartFile multipartFile) throws Exception{
ResponseModel responseModel;
File file = new File(workPath+"cad.dwg");
try{
//ae许可初
multipartFile.transferTo(file);
String cmds = String.format("%s %s %s %s %s",pythonEnvPath,pythonCodePath,workPath+"cad.dwg",dwgSpatial,outSpatial);
Process pcs = Runtime.getRuntime().exec(cmds);
pcs.waitFor();
StringBuilder res = new StringBuilder();
BufferedInputStream bis = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(bis));
String lineStr = "";
while ((lineStr = br.readLine()) != null) {
res.append(lineStr);
}
br.close();
bis.close();
StringBuilder jsonStr= new StringBuilder();
if(res.toString().equals("success")){
FileReader fileReader = new FileReader(workPath+"data.json");
BufferedReader jsonBr = new BufferedReader(fileReader);
String str="";
while ((str = jsonBr.readLine()) != null){
jsonStr.append(str);
}
responseModel = new ResponseModel(200,jsonStr.toString(),"success");
jsonBr.close();
fileReader.close();
}else{
responseModel = new ResponseModel(500,null, res.toString());
}
return responseModel;
} catch (IOException e) {
responseModel = new ResponseModel(500,null,e.getMessage());
return responseModel;
}finally{
file.delete();
}
}
}