意義
等值線是GIS制圖中常見的功能,在實際中經常需要基于CAD圖紙對資料進行等值線分析,等值線的型別主要有:等高線、等深線、等溫線(等氣溫線、等水溫線)、等壓線(水平面等壓線、垂直面等壓線)、等降水量線、等太陽輻射量線、等鹽度線、等PH值線、等太陽高度線、等潛水位線、等承壓水位線等,
通過分析等值線,我們可以判讀等高線來判斷地形的坡度的陡與緩,確定山脈的走向;通過判讀等深線來判斷海洋地形的種類如大陸架、海溝、海盆、海嶺、海底火山等;通過判讀大氣等壓線來判斷氣壓中心的名稱:如氣旋、反氣旋、高壓脊、低壓糟、輪廓;判斷不同部位的天氣特點,風向與風力大小;通過判讀大氣等溫線來判斷所在地的南北半球、季節與天氣;通過判讀等降水量線結合具體的地形輪廓判定山地的迎風坡與背風坡等;通過判讀人口密度等值線分析某地區人口分布的規律及其影響的自然、歷史、社會、經濟諸因素,
實作原理
等值線的原理
-
等值性或同距性原理 在等值線圖中,相鄰的兩條等值線要么等值,要么同距,
-
低高低和高低高原理 低值凸向高值,凸處的值變低 高值凸向低值,凸處的值變高
-
疏差小和密差大原理 等值線越稀疏,單位距離的差值越小 等值線越 密集,單位距離的差值越大
用程式繪制等值線的方法一般有:
-
Delaunay三角剖分(Delaunay Triangulation)相關知識 http://www.cnblogs.com/soroman/archive/2007/05/17/750430.html
-
矩形網格線法 https://www.baidu.com/link?url=qgnhaBc745ZNHND9Ulu4iFrSyRx2gcpZ2LkCZcx9oFhNp3NQFvf3KnbnFxp4b_NBmb5Z0_sPeqQ2Pqb3gnYMM_&wd=&eqid=d7d7fcd7000643850000000362fcec43
-
克里金法(Kriging) https://baike.baidu.com/item/%E5%85%8B%E9%87%8C%E9%87%91%E6%B3%95/5129539?fr=aladdin
-
在著名的開源GIS演算法庫Turfjs http://turfjs.org/ 中也有等值線的演算法
isolines
實作
先上效果圖

以下的實作代碼已開源至github, 地址: https://github.com/vjmap/vjmap-playground/blob/main/src/11geo_%E5%87%A0%E4%BD%95%E8%AE%A1%E7%AE%97/geoVectorContour.js
實作步驟:
(1) Web端在線打開CAD圖
如何在Web網頁端展示CAD圖形(唯杰地圖云端圖紙管理平臺 https://vjmap.com/app/cloud),這個在前面的博文中已講過,這里不再重復,有需要的朋友可下載工程源代碼研究下,
(2) 利用資料生成等值線
為了防止生成等值線的程序造成頁面卡頓,這里把演算法放到了webworker中來進行計算
//生成測驗資料
let dataMinValue = https://www.cnblogs.com/vjmap/p/10; // 資料最小值
let dataMaxValue = 500; // 資料最大值
let dataset = {"type" : "FeatureCollection",
"features" : []
};
?
// 區間顏色值
let colors = ["#006837", "#1a9850", "#66bd63", "#a6d96a", "#d9ef8b", "#ffffbf","#fee08b",
"#fdae61", "#f46d43", "#d73027", "#a50026"];
?
for (let i = 0; i < 100; i++) {
let feature={
"type" : "Feature",
"properties" : {
"value" : vjmap.randInt(dataMinValue, dataMaxValue) // 在最大值最小值范圍內隨機生成一個測驗資料
},
"geometry" : {
"type" : "Point",
"coordinates" : map.toLngLat(mapBounds.randomPoint())
}
};
dataset.features.push(feature);
}
?
let contoursSize = 20; // 等值面分級區間數,這里設定為20,可以自行設定
const createContour = async (dataset, contoursSize, propField, colors, dataMinValue, dataMaxValue, maxHeight, model) => {
let contours = [];
for(let i = 0; i < contoursSize; i++) {
contours.push(dataMinValue + (dataMaxValue - dataMinValue) * i / (contoursSize - 1));
}
?
let interpolateInput = [], interpolateOutput = [];
for(let i = 0; i < colors.length; i++) {
interpolateInput.push(i / (colors.length - 1)); // 插值輸入值,這里輸入0-1之間的比例
interpolateOutput.push(colors[i]) // 插值輸出值,這里輸入0-1之間的比例對應的顏色值
}
?
// 啟動webworker計算函式
let createContourWorker = vjmap.WorkerProxy(vjmap.vectorContour);
let { grid, contour } = await createContourWorker(dataset, propField, contours, {
model: model || 'exponential',
sigma2:0,
alpha:100
});
?
// 根據比例插值顏色
const mapProgressToValues = value =https://www.cnblogs.com/vjmap/p/> vjmap.interpolate(
interpolateInput,
interpolateOutput,
{ ease: vjmap.linear }
)(value)
?
// 把原資料的顏色也設定下,繪制marker需要
dataset.features.forEach(f => f.properties.color = mapProgressToValues((f.properties.value - dataMinValue) / (dataMaxValue - dataMinValue)))
?
let h = maxHeight; // 設定最大值要拉伸的高度
for(let i = 0; i < contour.features.length; i++) {
let prop = contour.features[i].properties;
let r = (prop.value - dataMinValue) / (dataMaxValue - dataMinValue);
prop.color = mapProgressToValues(r); // 插值出顏色值
prop.height = h * r; // 插值出要拉伸的高度值
}
return contour;
}
?
?
let maxHeight = map.pixelToHeight(100, map.getZoom()); // 設定最大值要拉伸的高度
let contour = await createContour(dataset, contoursSize,"value" /*geojson的哪個屬性值用于計算*/, colors, dataMinValue, dataMaxValue, maxHeight);
?
(3)繪制原始資料和生成好的等值線
let markers = null;
const addMarkers = ()=> {
if (markers) return;
markers = dataset.features.map(f => {
// 再隨機生成不同樣式的
let _marker = new vjmap.DiffusedApertureMarker({
lngLat: f.geometry.coordinates,
text: f.properties.value.toFixed(0)
}, {
// 可以給不同的屬性,如寬度,顏色,字體
width: 10,
colors: [f.properties.color, vjmap.randomColor()],
textFontSize: 14,
textColor: f.properties.color
}).createMarker();
_marker.addTo(map)
return _marker
})
}
const removeMarkers = ()=> {
if (!markers) return;
for(let i = markers.length - 1; i >= 0; i--) {
markers[i].remove();
}
markers = null;
}
?
let polyline = null;
const addPolyline = ()=> {
if (polyline) return;
polyline = new vjmap.Polyline({
data: contour,
lineColor: ['case', ['to-boolean', ['feature-state', 'hover']], '#00ffff', ['get', 'color']],
isHoverPointer: true,
isHoverFeatureState: true
});
polyline.addTo(map);
polyline.clickPopup(f => `<h3>值: ${f.properties.value.toFixed(2)}</h3>Color: ${f.properties.color}`, { anchor: 'bottom' });
}
const removePolyline = ()=> {
if (!polyline) return;
polyline.remove();
polyline = null;
}

(4)生成等值面
let polygon = null;
const addPolygon = ()=> {
if (polygon) return;
polygon = new vjmap.Polygon({
data: contour,
fillColor: ['case', ['to-boolean', ['feature-state', 'hover']], '#00ffff', ['get', 'color']],
fillOpacity: 0.9,
isHoverPointer: true,
isHoverFeatureState: true
});
polygon.addTo(map);
polygon.clickPopup(f => `<h3>值: ${f.properties.value.toFixed(2)}</h3>Color: ${f.properties.color}`, { anchor: 'bottom' });
}
const removePolygon = ()=> {
if (!polygon) return;
polygon.remove();
polygon = null;
}

(4)生成等值面拉伸
let fillExtrusions = null;
const addFillExtrusion = ()=> {
if (fillExtrusions) return;
fillExtrusions = new vjmap.FillExtrusion({
data: contour,
fillExtrusionColor: ['case', ['to-boolean', ['feature-state', 'hover']], '#00ffff', ['get', 'color']],
fillExtrusionOpacity: 0.9,
fillExtrusionHeight: ['get', 'height'],
fillExtrusionBase:0,
isHoverPointer: true,
isHoverFeatureState: true
});
fillExtrusions.addTo(map);
fillExtrusions.clickPopup(f => `<h3>值: ${f.properties.value.toFixed(2)}</h3>Color: ${f.properties.color}`, { anchor: 'bottom' });
}
const removeFillExtrusion = ()=> {
if (!fillExtrusions) return;
fillExtrusions.remove();
fillExtrusions = null;
}

以上的實作代碼已開源至github, 地址: https://github.com/vjmap/vjmap-playground/blob/main/src/11geo_%E5%87%A0%E4%BD%95%E8%AE%A1%E7%AE%97/geoVectorContour.js
在線體驗地址為:https://vjmap.com/demo/#/demo/map/geo/geoVectorContour
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/502146.html
標籤:GIS
