? 隨著web在線CAD圖查看的普及,需求也不斷涌現,一些需求不再滿足的在線圖形的查看,而涉及到web端在線圖形的幾何運算,本文以如果實作與在線CAD圖中的線段實時求交點這例,介紹下如何在web端cad圖幾何運算的功能實作,
如果實作與在線CAD圖中的線段實時求交點
需要實作的功能有
- 在線查看CAD圖
- 獲取CAD圖上面的繪制的所有線段坐標
- 線段相交
- 實時計算相交
先上實作效果
實作效果圖

功能實作介紹
在線查看CAD圖
如果在Web網頁端展示CAD圖形(唯杰地圖云端圖紙管理平臺 https://vjmap.com/app/cloud),這個在前面的博文中已講過,這里不再重復,有需要的朋友可下載工程源代碼研究下,
獲取CAD圖上面的繪制的所有線段坐標
在線獲取CAD圖上所有線段坐標有兩種方式
在柵格模式下,可以去后臺通過條件查詢獲取所有線段坐標,代碼如下
//柵格樣式去服務器獲取坐標點資料
// 柵格樣式獲取捕捉點
// 查詢所有坐標資料,欄位含義可參考https://vjmap.com/guide/svrStyleVar.html
let res = await svc.conditionQueryFeature({ fields:"s3", condition:"s3 != ''", limit: 100000})
res = res.result.map(e => e.s3.split(";"))
snapObj.features = []
for(let item of res) {
let coordinates = []
for(let pt of item) {
const p = pt.split(",")
if (p.length >= 2) {
coordinates.push(map.toLngLat([+p[0], +p[1]]))
}
}
if (coordinates.length == 1) {
snapObj.features.push({
type: "Feature",
geometry: {
type: "Point",
coordinates: coordinates[0]
}
})
}
else if (coordinates.length > 1) {
snapObj.features.push({
type: "Feature",
geometry: {
type: "LineString",
coordinates: coordinates
}
})
}
}
在矢量模式下,可以直接在前端獲取當前渲染的線圖層的所有線坐標,代碼如下
// 查詢矢量圖層上所有的線圖層
let features = map.queryRenderedFeatures({layers: ['vector-layer-lines']})
let mapGeoDatas = {
type: "FeatureCollection",
features: features.map(f => {
return {
id: f.id,
type: f.type,
properties: f.properties,
geometry: f.geometry
}
})
}
線段相交
/**
* 線段相交
* @return {{result: string, status: boolean} | {result: string, status: boolean} | {x: number, y: number, status: boolean, ratio: number} | {result: string, status: boolean}}
*/
export function segmentIntersect(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): {
result: string;
status: boolean;
x?: undefined;
y?: undefined;
ratio?: undefined;
} | {
status: boolean;
x: number;
y: number;
ratio: number;
result?: undefined;
};
在示例中,我們模擬了一條隨機的線條,并且讓這條線條實時動起來,代碼如下
// 讓相交線動起來
const moveLine = (newStartPoint, newEndPoint) => {
let data = https://www.cnblogs.com/vjmap/p/map.getSourceData(intersectLine.sourceId);
let geoData = map.fromLngLat(data);
// 開始點插值函式
let mapProgressToValueStart = vjmap.interpolate(
[0, 1],
[geoData.features[0].geometry.coordinates[0], [newStartPoint.x, newStartPoint.y]]
)
// 終點插值函式
let mapProgressToValueEnd = vjmap.interpolate(
[0, 1],
[geoData.features[0].geometry.coordinates[1], [newEndPoint.x, newEndPoint.y]]
)
vjmap.createAnimation({
from: 0,
to: 1,
duration: 5000,
ease:vjmap.linear, //線性
onUpdate: latest => {
let beginPoint = mapProgressToValueStart(latest)
let endPoint = mapProgressToValueEnd(latest)
// 修改坐標
data.features[0].geometry.coordinates = map.toLngLat([beginPoint, endPoint])
map.setData(intersectLine.sourceId, data)
},
onComplete: (e) => {
map.fire("moveLineFinish"); // 發送線移動完成事件
}
})
}
實時相交
相交計算如果資料量大時,會耗CPU資源,會導致圖形卡頓,如果需要做到實時相交,并且運行界面不卡頓,需要用WebWorker的技術,web worker 是運行在后臺的 JavaScript,不會影響頁面的性能,web worker 無疑是解決 js 計算能力弱的一大利器.
在唯杰地圖 vjmap中有對webworker的封裝,可以直接把一個匿名函式做為一個webworker去運行,相關代碼如下
/* 如果要用vjmap庫中其他的函式,獲取庫腳本的內容
let script = await vjmap.httpHelper.get("js/vjmap/vjmap.min.js", undefined, {
raw: true
})*/
// 啟動webworker計算相交函式
let intersect = vjmap.WorkerProxy(getIntersects, {
// vjmap: script.data, //腳本內容, 如果要用vjmap庫中其他的函式,可以獲取庫腳本的內容 ,把腳本內容傳給webworker
intersectFunc: vjmap.segmentIntersect // 把主行程庫的相交函式做為背景關系傳進去,這個方法是不用引入vjmap整個庫,只用里面的某個函式,但是這個函式不能呼叫其他函式,如果呼叫了其他函式會報錯,這時只有用上面注釋的那個辦法,把整個vjmap庫都匯入進webworker
});
// 用webworker計算相交點
const calcIntersect = async ()=> {
// 獲取線的坐標
let coordinates = map.fromLngLat(map.getSourceData(intersectLine.sourceId)).features[0].geometry.coordinates;
// 啟動webworker計算相交點
let intersectPoints = await intersect(coordinates[0], coordinates[1], geoDatas)
intersectSymbols.setData(map.toLngLat(intersectPoints)); //修改資料
map.fire("calcIntersectFinish"); // 發送線移動完成事件
}
map.on("calcIntersectFinish", async ()=> setTimeout(async ()=> await calcIntersect(), 15))
calcIntersect();
// 如果要停止webworker
//intersect.worker.terminate()
最終效果如下

上面的案例代碼已開源,訪問 (https://vjmap.com/demo/#/demo/map/geo/geoWebWorkerIntersect) ,查看效果和代碼即可,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/500189.html
標籤:其他
