Men的博客

欢迎光临!

0%

是否在点、线、面内部

/**
* 判断鼠标交互位置是否在符号范围内
* @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));
}