import { Coordinate } from '../dependents'; import { Point } from '../interface'; import { getSectorPath } from './graphics'; import { isBetween } from './helper'; import { BBox } from './bbox'; /** * @ignore * Gets x dimension length * @param coordinate * @returns x dimension length */ export function getXDimensionLength(coordinate): number { if (coordinate.isPolar && !coordinate.isTransposed) { // 极坐标系下 width 为弧长 return (coordinate.endAngle - coordinate.startAngle) * coordinate.getRadius(); } // 直角坐标系 const start = coordinate.convert({ x: 0, y: 0 }); const end = coordinate.convert({ x: 1, y: 0 }); // 坐标系有可能发生 transpose 等变换,所有通过两点之间的距离进行计算 return Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)); } /** * @ignore * Determines whether full circle is * @param coordinate * @returns true if full circle */ export function isFullCircle(coordinate: Coordinate): boolean { if (coordinate.isPolar) { const { startAngle, endAngle } = coordinate; return endAngle - startAngle === Math.PI * 2; } return false; } /** * @ignore * 获取当前点到坐标系圆心的距离 * @param coordinate 坐标系 * @param point 当前点 * @returns distance to center */ export function getDistanceToCenter(coordinate: Coordinate, point: Point): number { const center = coordinate.getCenter() as Point; return Math.sqrt((point.x - center.x) ** 2 + (point.y - center.y) ** 2); } /** * @ignore * 坐标点是否在坐标系中 * @param coordinate * @param point */ export function isPointInCoordinate(coordinate: Coordinate, point: Point) { let result = false; if (coordinate) { if (coordinate.type === 'theta') { const { start, end } = coordinate; result = isBetween(point.x, start.x, end.x) && isBetween(point.y, start.y, end.y); } else { const invertPoint = coordinate.invert(point); result = isBetween(invertPoint.x, 0, 1) && isBetween(invertPoint.y, 0, 1); } } return result; } /** * @ignore * 获取点到圆心的连线与水平方向的夹角 */ export function getAngleByPoint(coordinate: Coordinate, point: Point): number { const center = coordinate.getCenter(); return Math.atan2(point.y - center.y, point.x - center.x); } /** * @ignore * 获取同坐标系范围相同的剪切区域 * @param coordinate * @returns */ export function getCoordinateClipCfg(coordinate: Coordinate, margin: number = 0) { const { start, end } = coordinate; const width = coordinate.getWidth(); const height = coordinate.getHeight(); if (coordinate.isPolar) { const { startAngle, endAngle } = coordinate; const center = coordinate.getCenter(); const radius = coordinate.getRadius(); return { type: 'path', startState: { path: getSectorPath(center.x, center.y, radius + margin, startAngle, startAngle), }, endState: (ratio) => { const diff = (endAngle - startAngle) * ratio + startAngle; const path = getSectorPath(center.x, center.y, radius + margin, startAngle, diff); return { path, }; }, attrs: { path: getSectorPath(center.x, center.y, radius + margin, startAngle, endAngle), }, }; } let endState; if (coordinate.isTransposed) { endState = { height: height + margin * 2, }; } else { endState = { width: width + margin * 2, }; } return { type: 'rect', startState: { x: start.x - margin, y: end.y - margin, width: coordinate.isTransposed ? width + margin * 2 : 0, height: coordinate.isTransposed ? 0 : height + margin * 2, }, endState, attrs: { x: start.x - margin, y: end.y - margin, width: width + margin * 2, height: height + margin * 2, }, }; } /** * 获取坐标系范围的 BBox * @param coordinate * @param margin */ export function getCoordinateBBox(coordinate: Coordinate, margin = 0) { const { start, end } = coordinate; const width = coordinate.getWidth(); const height = coordinate.getHeight(); const minX = Math.min(start.x, end.x); const minY = Math.min(start.y, end.y); return BBox.fromRange(minX - margin, minY - margin, minX + width + margin, minY + height + margin); }