如何在前端通過JavaScript建立修改CAD圖形

vjmap 發表於 2021-10-18
前端 JavaScript

背景

在之前的博文CAD圖DWG解析WebGIS視覺化技術分析總結CAD_DWG圖Web視覺化一站式解決方案-唯傑地圖-vjmap中講解了如何把CAD的DWG格式的圖紙Web視覺化的方案,那在Web前端能不能通過JavaScript建立或基於現在的CAD圖形進行修改呢?

現狀

建立修改CAD圖形,一般是基於AutoCAD進行二次開發,ObjectARX是AutoDesk公司針對AutoCAD平臺上的二次開發而推出的一個開發軟體包,它提供了以C++為基礎的物件導向開發環境應用程式介面,能真正快速的訪問AutoCAD圖形資料庫。 與以往的 AutoCAD 二次開發工具 AutoLISP 和ADS不同,ObjectARX應用程式是一個DLL(動態連結庫),共享AutoCAD的地址空間,對AutoCAD進行直接函式呼叫。所以,使用ARX程式設計的函式的執行速度得以大大提高。ARX 類庫採用了標準的C++類庫的封裝形式,這也大大提高了程式設計師程式設計的可靠度和效率。

運用ObjectARX進行二次開發,必須首先設定好ObjectARX的開發環境。常用的開發環境是Microsoft Visual C++ 6.0 、Microsoft visual studio 2005、Microsoft visual studio 2008、Microsoft visual studio 2010。同時,還需要安裝ObjectARX SDK。

Visual C++、ObjectARX等開發語言和環境肯定嚇跑了不少開發者。那對於一些簡單的場景,如只要根據資料自動成圖或者在現在的圖形上做一些很簡單的修改,有沒有一個簡單的辦法或語言和開發環境?

JS新建修改CAD圖形

唯傑地圖在前端實現了常用的AutoCAD實體封裝,能通過JavaScript指令碼建立新的CAD圖形。

支援的CAD實體型別

類名稱 說明
DbLine 直線
DbCurve 曲線
Db2dPolyline 二維折線
Db3dPolyline 三維多段線
DbPolyline 多段線
BlockReference 塊參照
DbArc 圓弧
DbCircle
DbEllipse 橢圓
DbHatch 填充
Text 單行文字
DbMText 多行文字
RasterImage 柵格圖片
DbShape 型實體
Spline 樣條曲線
Wipeout 遮罩實體
Dimension 標註
Db2LineAngularDimension 角度標註[兩條線]
Db3PointAngularDimension 角度標註[三點]
DbAlignedDimension 對齊標註
DbArcDimension 圓弧標註
DbDiametricDimension 直徑標註
DbOrdinateDimension 座標標註
DbRadialDimension 半徑標註
DbRadialDimensionLarge 半徑折線標註
DbRotatedDimension 轉角標註
DbLayer 圖層
DbTextStyle 文字樣式
DbDimStyle 標註樣式
DbLinetypeStyle 線型樣式
DbBlock 塊定義
DbDocument 資料庫文件

下面以新建一個籃球場示意圖以例,相關程式碼如下:

(async () => {
	// --新建地圖--在後臺新建CAD圖,然後在前端開啟
	// js程式碼
	let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
	let doc = new vjmap.DbDocument();
	let entitys = [];
	let line1 = new vjmap.DbLine();
	line1.start = [0, 0]
	line1.end = [0, 15]
	entitys.push(line1)

	let line2 = new vjmap.DbLine();
	line2.start = [0, 14.1]
	line2.end = [2.99, 14.1]
	entitys.push(line2)

	let line3 = new vjmap.DbLine();
	line3.start = [0, 0.9]
	line3.end = [2.99, 0.9]
	entitys.push(line3)

	let line4 = new vjmap.DbLine();
	line4.start = [0, 9.95]
	line4.end = [5.8, 9.95]
	entitys.push(line4)

	let line5 = new vjmap.DbLine();
	line5.start = [0, 5.05]
	line5.end = [5.8, 5.05]

	let hatch = new vjmap.DbHatch();
	hatch.pattern = "SOLID";
	hatch.color = 0xB43F32;
	hatch.points = [line4.start, line4.end, line5.end, line5.start];
	entitys.push(hatch);
	entitys.push(line4)
	entitys.push(line5)

	let line6 = new vjmap.DbLine();
	line6.start = [5.8, 5.05]
	line6.end = [5.8, 9.95]
	entitys.push(line6)

	let arc1 = new vjmap.DbArc();
	arc1.center = [5.7963, 7.504];
	arc1.radius = 1.8014;
	arc1.startAngle = 270 * Math.PI / 180.0;
	arc1.endAngle = 90 * Math.PI / 180.0;
	entitys.push(arc1)

	let arc2 = new vjmap.DbArc();
	arc2.center = [5.7963, 7.504];
	arc2.radius = 1.8014;
	arc2.startAngle = 90 * Math.PI / 180.0;
	arc2.endAngle = 270 * Math.PI / 180.0;
	//arc2.linetype = "DASHED"
	entitys.push(arc2)

	let arc3 = new vjmap.DbArc();
	arc3.center = [1.575, 7.5];
	arc3.radius = 6.75;
	arc3.startAngle = 282 * Math.PI / 180.0;
	arc3.endAngle = 78 * Math.PI / 180.0;
	entitys.push(arc3)

	let block = new vjmap.DbBlock();
	block.name = "ball";
	block.origin = [0, 0]
	block.entitys = entitys;
	doc.appendBlock(block);

	let blockRef1 = new vjmap.DbBlockReference();
	blockRef1.blockname = "ball";
	blockRef1.position = [0, 0];
	doc.appendEntity(blockRef1);

	let blockRef2 = new vjmap.DbBlockReference();
	blockRef2.blockname = "ball";
	blockRef2.position = [28, 15];
	blockRef2.rotation = Math.PI;
	doc.appendEntity(blockRef2);

	let otherEnts = [
		new vjmap.DbLine({
			start: [0, 15],
			end: [28, 15]
		}),
		new vjmap.DbLine({
			start: [0, 0],
			end: [28, 0]
		}),
		new vjmap.DbLine({
			start: [14, 0],
			end: [14, 15],
			colorIndex: 1
		}),
		new vjmap.DbCircle({
			center:[14, 7.5],
			radius: 1.83,
			color: 0xFF0000
		}),
		new vjmap.DbText({
			position: [14, 16],
			contents: "籃球場示意圖",
			colorIndex: 1,
			horizontalMode: 4,
			height: 1,
		})
	]

	doc.appendEntity(otherEnts);

	// js程式碼
	let res = await svc.updateMap({
		mapid: "basketballCourt",
		filedoc: doc.toDoc(),
		mapopenway: vjmap.MapOpenWay.Memory,
		style: vjmap.openMapDarkStyle() // div為深色背景顏色時,這裡也傳深色背景樣式
	})
	if (res.error) {
		message.error(res.error)
	}
	let mapExtent = vjmap.GeoBounds.fromString(res.bounds);
	let prj = new vjmap.GeoProjection(mapExtent);

	var map = new vjmap.Map({
		container: 'map', // container ID
		style: svc.rasterStyle(),
		center: prj.toLngLat(mapExtent.center()),
		zoom: 2,
		renderWorldCopies: false
	});
	map.attach(svc, prj);
	map.fitMapBounds();

	map.addControl(new vjmap.NavigationControl());
	map.addControl(new vjmap.MousePositionControl({showZoom: true}));

	map.enableLayerClickHighlight(svc, e => {
		e && message.info(`type: ${e.name}, objectid: ${e.objectid}, layer: ${e.layerindex}`);
	})
})();

建立完後,Web顯示如下:

image-20211018195709908

把建立的DWG圖形,在AutoCAD裡面可以開啟此圖:

image-20211018200747551

修改或刪除

修改通過from屬性設定 來源於哪個圖,會在此圖的上面進行修改或新增刪除,格式如 形式為 mapid/version,如 exam/v1 .

刪除的話,指定圖中實體的objectID

示例程式碼如下:

let doc = new vjmap.DbDocument();
/** 來源於哪個圖,會在此圖的上面進行修改或新增刪除,格式如 形式為 mapid/version,如 exam/v1 . */
doc.from = "basketballCourt/v1";

// 修改或刪除實體是通過傳遞 `objectid` 實體控制程式碼,如果沒有 `objectid` 則表示新增
let modifyEnts = [
    /*修改*/
    new vjmap.DbCircle({
        objectid: "71",// 實體控制程式碼,如傳了實體控制程式碼,是表示修改或刪除此實體. 
        colorIndex: 2
    }),
    /*刪除*/
    new vjmap.DbText({
        objectid: "73",// 實體控制程式碼,如傳了實體控制程式碼,是表示修改或刪除此實體. 
        delete: true // 表示刪除
    }),
    /*新增(沒有傳 objectid )*/
    new vjmap.DbMText({
        position: [14, -2],
        contents: "我是多行文字",
        colorIndex: 3,
        attachment: 2,
        height: 1,
    })
]
doc.appendEntity(modifyEnts);

// js程式碼
let res = await svc.updateMap({
    mapid: "newBasketballCourt",
    filedoc: doc.toDoc(),
    mapopenway: vjmap.MapOpenWay.Memory,
    style: vjmap.openMapDarkStyle() // div為深色背景顏色時,這裡也傳深色背景樣式
})

結果如下:

image-20211018201221961

可以訪問 demo地址 https://vjmap.com/guide/newmap.html 去體驗下效果

應用場景

適用於在前端有資料,需要線上建立或基於現在CAD圖形進行修改或刪除;如可獲取全國的GeoJson資料建立一個CAD圖形;對於一些經常變化的資料如工程進度圖紙根據進度資料實時繪製生成DWG圖紙等場景;對於專業複雜的圖形繪製或編輯工作,建議使用ObjectARX對AutoCAD進行二次開發實現!