/**
* 判断鼠标交互位置是否在符号范围内
* @param {number} anchorX - 鼠标交互位置X
* @param {number} anchorY - 鼠标交互位置Y
* @param {number} screenX - 点所在屏幕坐标X
* @param {number} screenY - 点所在屏幕坐标Y
*/
contain(anchorX, anchorY, screenX, screenY) {
return Math.sqrt((anchorX - screenX) * (anchorX - screenX) + (anchorY - screenY) * (anchorY - screenY)) <= this.radius;
}
/**
* 是否包含传入坐标
* @remarks
* 线是1维,所以要设置一个tolerance容差,来判断坐标是否落到线上
* @param {number} screenX - 鼠标屏幕坐标X
* @param {number} screenX - 鼠标屏幕坐标Y
* @return {boolean} 是否落入
*/
contain(screenX: number, screenY: number): boolean {
let p2;
//from Leaflet
//点到线段的距离,垂直距离
const _distanceToSegment = (p, p1, p2) => {
let x = p1[0],
y = p1[1],
dx = p2[0] - x,
dy = p2[1] - y,
dot = dx * dx + dy * dy,
t;
if (dot > 0) {
t = ((p[0] - x) * dx + (p[1] - y) * dy) / dot;
if (t > 1) {
x = p2[0];
y = p2[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p[0] - x;
dy = p[1] - y;
return Math.sqrt(dx * dx + dy * dy);
}
const distance = this._screen.reduce( (acc, cur) => {
if (p2) {
const p1 = p2;
p2 = cur;
return Math.min(acc, _distanceToSegment([screenX, screenY], p1, p2));
} else {
p2 = cur;
return acc;
}
}, Number.MAX_VALUE);
return distance <= this._tolerance;
}
/**
* 是否包含传入坐标
* @remarks
* 点是不是落在面内
* from https://github.com/substack/point-in-polygon
* ray-casting algorithm based on
* http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
* @param {number} screenX - 鼠标屏幕坐标X
* @param {number} screenX - 鼠标屏幕坐标Y
* @return {boolean} 是否落入
*/
contain(screenX: number, screenY: number): boolean {
const first = this._screen[0];
const others = this._screen.slice(1);
//first ring contained && others no contained
const _pointInPolygon = (point, vs) => {
let x = point[0], y = point[1];
let inside = false;
for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) {
let xi = vs[i][0], yi = vs[i][1];
let xj = vs[j][0], yj = vs[j][1];
let intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
};
return _pointInPolygon([screenX, screenY], first) && others.every(ring => !_pointInPolygon([screenX, screenY], ring));
//return this._screen.some(ring => this._pointInPolygon([screenX, screenY], ring));
}