gis中的三维,少不了表面量算和空间量算。
表面量算:依地形起伏、贴模型表面变化的长度、面积等量算。
空间量算:欧式直线距离或椭球曲面距离、横截面面积。
空间距离:很简单,计算两点的直线距离即可。
空间面积:取中间点,或质心,与各个边组成三角形。计算每个三角形的面积。(该方法不适用与自相交的多边形)
今天主要探讨表面距离的计算思路:
实现代码:
/**
* 计算线段的表面距离
* @param startPoint -线段起点的屏幕坐标
* @param endPoint -线段终点的屏幕坐标
* @returns 表面距离
*/
private calculateSurfaceDistance(
startPoint: Cesium.Cartesian2,
endPoint: Cesium.Cartesian2
):number{
let resultDistance =0;
const sampleWindowPoints = [startPoint];
const length =Math.sqrt(Math.pow(endPoint.x - startPoint.x,2) + (endPoint.y - startPoint.y,2)) ;
for(let ii = 50; ii <= length; ii ++){
const tempPositon = findWindowPositionByPixelInterval(startPoint,endPoint,ii);
sampleWindowPoints.push(tempPositon);
}
sampleWindowPoints.push(endPoint);
for(let jj =0; jj < sampleWindowPoints.length-1; jj ++){
resultDistance += this.calculateDetailSurfaceLength(sampleWindowPoints[jj + 1],sampleWindowPoints[jj]);
}
return resultDistance;
}
/**
* 计算细分后的,每一小段的笛卡尔坐标距离(也就是大地坐标系距离)
* @param startPoint -每一段线段起点
* @param endPoint -每一段线段终点
* @returns 表面距离
*/
private calculateDetailSurfaceLength(startPoint:Cesium.Cartesian2,endPoint:Cesium.Cartesian2):number{
let innerS = 0;
const surfaceStartCartesian3 = pickCartesian(this.viewer,startPoint);
const surfaceEndCartesian3 = pickCartesian(this.viewer,endPoint);
if(typeof(surfaceStartCartesian3.cartesian) !== 'undefined' && typeof(surfaceEndCartesian3.cartesian) !== 'undefined'){
const cartographicStart = Cesium.Cartographic.fromCartesian(surfaceStartCartesian3.cartesian);
const cartographicEnd = Cesium.Cartographic.fromCartesian(surfaceEndCartesian3.cartesian);
const geoD = new Cesium.EllipsoidGeodesic();
geoD.setEndPoints(cartographicStart,cartographicEnd);
innerS = geoD.surfaceDistance;
innerS = Math.sqrt(
Math.pow(innerS, 2) +
Math.pow(cartographicStart.height - cartographicEnd.height, 2)
);
}
return innerS;
}
/**
* 获取线段上距起点一定距离出的线上点坐标(屏幕坐标)
* @param startPosition -线段起点(屏幕坐标)
* @param endPosition -线段终点(屏幕坐标)
* @param interval -距起点距离
* @returns -结果坐标(屏幕坐标)
*/
export function findWindowPositionByPixelInterval(startPosition:Cesium.Cartesian2,endPosition:Cesium.Cartesian2,interval:number):Cesium.Cartesian2{
let result = new Cesium.Cartesian2(0,0);
const length = Math.sqrt(Math.pow(endPosition.x - startPosition.x,2) + Math.pow(endPosition.y - startPosition.y,2));
if(length< interval){
return result;
}else{
const x = (interval/length)*(endPosition.x - startPosition.x) + startPosition.x;
//alert(interval/length)
const y = (interval/length)*(endPosition.y - startPosition.y) + startPosition.y;
result.x = x;
result.y = y;
}
return result;
}
看下表面距离和空间距离的结果对比: