绘制直线,我们可以拿到形成直线的点集合数据;那我们只要求坐标点到这个直线的距离是否在范围内就可以解决问题。
那这里用的是坐标点与直线两端形成的夹角,判断两边夹角来判断坐标点出直线什么位置(线内、线外),线内的话算出点到线的垂直距离,线外求点带直线两端的距离
注意:由于我们需要的直线夹角是在180度之内,但在计算时由于形成直线方向的问题,会出现大于180的直线夹角,解决这个问题我们是判断所有大于180度的夹角,用360减去夹角得到想要的直线想成的夹角; 还有如果是多段线形成的直线,最后结果不要忘记筛重
/**
* 求点到直线的距离
* @param latlngs 形成直线的点集合
*/
toLineDistance(latlngs){
var lineRangeDevice = []
for(let i = 0;i < latlngs.length-1;i++){
var startDot = latlngs[i],
endDot = latlngs[i+1];
for (let i in this.allMarkers) {
let marker = this.allMarkers[i];
// 计算设备-结束点形成的直线 与 起始点-结束点形成直线的夹角
let endDotAngle = this.getLineAngle({
x:this.rad(marker.position.lng) - this.rad(endDot.lng),
y:this.rad(marker.position.lat) - this.rad(endDot.lat)
},{
x:this.rad(startDot.lng) - this.rad(endDot.lng),
y:this.rad(startDot.lat) - this.rad(endDot.lat)
})
if(endDotAngle > 180){
endDotAngle = 360 - endDotAngle
}
// 计算设备-起始点形成的直线 与 起始点-结束点形成直线的夹角
let startDotAngle = this.getLineAngle({
x:this.rad(marker.position.lng) - this.rad(startDot.lng),
y:this.rad(marker.position.lat) - this.rad(startDot.lat)
},{
x:this.rad(endDot.lng) - this.rad(startDot.lng),
y:this.rad(endDot.lat) - this.rad(startDot.lat)
})
if(startDotAngle > 180){
startDotAngle = 360 - startDotAngle
}
// 夹角小于90度
if(startDotAngle < 90 && endDotAngle < 90){
let endDotDistance = this.geoDistance(marker.position.lat, marker.position.lng, endDot.lat, endDot.lng) * 1000
//获得弧度
let radian = 2 * Math.PI / 360 * endDotAngle;
let distance = Math.sin(radian) * endDotDistance //对边
if(distance <= this.distanceRange){
lineRangeDevice.push(marker.data.data)
}
}else{
let startDotDistance = this.geoDistance(marker.position.lat, marker.position.lng, startDot.lat, startDot.lng) * 1000
let endDotDistance = this.geoDistance(marker.position.lat, marker.position.lng, endDot.lat, endDot.lng) * 1000
if(
(startDotDistance <= this.distanceRange) ||
(endDotDistance <= this.distanceRange)
){
lineRangeDevice.push(marker.data.data)
}
}
}
}
let devices = Array.from(new Set(lineRangeDevice))
},
求直线夹角,参数是另外两点与相交点的坐标差
// 求两条直线角度
getLineAngle: ({ x: x1, y: y1 }, { x: x2, y: y2 }) => {
const dot = x1 * x2 + y1 * y2
const det = x1 * y2 - y1 * x2
const angle = Math.atan2(det, dot) / Math.PI * 180
return (angle + 360) % 360
},
//经纬度转换成三角函数中度分表形式。
rad:function(d) {
return d * Math.PI / 180.0;
},
计算两点间的距离,也可以用leaflet提供的distance方法
/**
* 计算两个经纬度间的距离
* @param lat1 纬度
* @param lng1 经度
* @param lat2 纬度
* @param lng2 经度
*/
geoDistance:function(lat1, lng1, lat2, lng2) {
let radLat1 = this.rad(lat1);
let radLat2 = this.rad(lat2);
let a = radLat1 - radLat2;
let b = this.rad(lng1) - this.rad(lng2);
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137;// EARTH_RADIUS;
s = Math.round(s * 10000) / 10000; //输出为公里
return s;
},