UNPKG

@mapgis/webclient-es6-mapboxgl

Version:

206 lines (179 loc) 7.23 kB
import { Common } from '@mapgis/webclient-es6-service'; const { Zondy } = Common; import {Curve as LevelRendererCurve} from './Curve'; import {Vector as LevelRendererVector} from './Vector'; /** * @private * @class Zondy.LevelRenderer.Tool.ComputeBoundingBox * @classdesc LevelRenderer 工具-图形 Bounds 计算 */ class ComputeBoundingBox { /** * @function Zondy.LevelRenderer.Tool.ComputeBoundingBox.prototype.constructor * @description 构造函数。 */ constructor() { if (arguments.length === 3) { this.computeBoundingBox(arguments); } this.CLASS_NAME = "Zondy.LevelRenderer.Tool.ComputeBoundingBox"; } /** * @function Zondy.LevelRenderer.Tool.ComputeBoundingBox.prototype.computeBoundingBox * @description 从顶点数组中计算出最小包围盒,写入'min'和'max'中。 * @param {Array.<Object>} points - 顶点数组。 * @param {Array} min - 最小 * @param {Array} max - 最大 */ computeBoundingBox(points, min, max) { if (points.length === 0) { return; } var left = points[0][0]; var right = points[0][0]; var top = points[0][1]; var bottom = points[0][1]; for (var i = 1; i < points.length; i++) { var p = points[i]; if (p[0] < left) { left = p[0]; } if (p[0] > right) { right = p[0]; } if (p[1] < top) { top = p[1]; } if (p[1] > bottom) { bottom = p[1]; } } min[0] = left; min[1] = top; max[0] = right; max[1] = bottom; } /** * @function Zondy.LevelRenderer.Tool.ComputeBoundingBox.prototype.cubeBezier * @description 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入'min'和'max'中。原:computeCubeBezierBoundingBox。 * @param {Array.<number>} p0 - 三阶贝塞尔曲线p0点 * @param {Array.<number>} p1 - 三阶贝塞尔曲线p1点 * @param {Array.<number>} p2 - 三阶贝塞尔曲线p2点 * @param {Array.<number>} p3 - 三阶贝塞尔曲线p3点 * @param {Array.<number>} min - 最小 * @param {Array.<number>} max - 最大 */ cubeBezier(p0, p1, p2, p3, min, max) { var curve = new LevelRendererCurve(); var xDim = []; curve.cubicExtrema(p0[0], p1[0], p2[0], p3[0], xDim); for (let i = 0; i < xDim.length; i++) { xDim[i] = curve.cubicAt(p0[0], p1[0], p2[0], p3[0], xDim[i]); } var yDim = []; curve.cubicExtrema(p0[1], p1[1], p2[1], p3[1], yDim); for (let i = 0; i < yDim.length; i++) { yDim[i] = curve.cubicAt(p0[1], p1[1], p2[1], p3[1], yDim[i]); } xDim.push(p0[0], p3[0]); yDim.push(p0[1], p3[1]); var left = Math.min.apply(null, xDim); var right = Math.max.apply(null, xDim); var top = Math.min.apply(null, yDim); var bottom = Math.max.apply(null, yDim); min[0] = left; min[1] = top; max[0] = right; max[1] = bottom; } /** * @function Zondy.LevelRenderer.Tool.ComputeBoundingBox.prototype.quadraticBezier * @description 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入'min'和'max'中。原:computeQuadraticBezierBoundingBox。 * @param {Array.<number>} p0 - 二阶贝塞尔曲线p0点 * @param {Array.<number>} p1 - 二阶贝塞尔曲线p1点 * @param {Array.<number>} p2 - 二阶贝塞尔曲线p2点 * @param {Array.<number>} min - 最小 * @param {Array.<number>} max - 最大 */ quadraticBezier(p0, p1, p2, min, max) { var curve = new LevelRendererCurve(); // Find extremities, where derivative in x dim or y dim is zero var t1 = curve.quadraticExtremum(p0[0], p1[0], p2[0]); var t2 = curve.quadraticExtremum(p0[1], p1[1], p2[1]); t1 = Math.max(Math.min(t1, 1), 0); t2 = Math.max(Math.min(t2, 1), 0); var ct1 = 1 - t1; var ct2 = 1 - t2; var x1 = ct1 * ct1 * p0[0] + 2 * ct1 * t1 * p1[0] + t1 * t1 * p2[0]; var y1 = ct1 * ct1 * p0[1] + 2 * ct1 * t1 * p1[1] + t1 * t1 * p2[1]; var x2 = ct2 * ct2 * p0[0] + 2 * ct2 * t2 * p1[0] + t2 * t2 * p2[0]; var y2 = ct2 * ct2 * p0[1] + 2 * ct2 * t2 * p1[1] + t2 * t2 * p2[1]; min[0] = Math.min(p0[0], p2[0], x1, x2); min[1] = Math.min(p0[1], p2[1], y1, y2); max[0] = Math.max(p0[0], p2[0], x1, x2); max[1] = Math.max(p0[1], p2[1], y1, y2); } /** * @function Zondy.LevelRenderer.Tool.ComputeBoundingBox.prototype.arc * @description 从圆弧中计算出最小包围盒,写入'min'和'max'中。原:computeArcBoundingBox。 * @param {number} x - 圆弧中心点 x * @param {number} y - 圆弧中心点 y * @param {number} r - 圆弧半径 * @param {number} startAngle - 圆弧开始角度 * @param {number} endAngle - 圆弧结束角度 * @param {number} anticlockwise - 是否是顺时针 * @param {number} min - 最小 * @param {number} max - 最大 */ arc(x, y, r, startAngle, endAngle, anticlockwise, min, max) { var vec2 = new LevelRendererVector(); var start = vec2.create(); var end = vec2.create(); var extremity = vec2.create(); start[0] = Math.cos(startAngle) * r + x; start[1] = Math.sin(startAngle) * r + y; end[0] = Math.cos(endAngle) * r + x; end[1] = Math.sin(endAngle) * r + y; vec2.min(min, start, end); vec2.max(max, start, end); // Thresh to [0, Math.PI * 2] startAngle = startAngle % (Math.PI * 2); if (startAngle < 0) { startAngle = startAngle + Math.PI * 2; } endAngle = endAngle % (Math.PI * 2); if (endAngle < 0) { endAngle = endAngle + Math.PI * 2; } if (startAngle > endAngle && !anticlockwise) { endAngle += Math.PI * 2; } else if (startAngle < endAngle && anticlockwise) { startAngle += Math.PI * 2; } if (anticlockwise) { var tmp = endAngle; endAngle = startAngle; startAngle = tmp; } // var number = 0; // var step = (anticlockwise ? -Math.PI : Math.PI) / 2; for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { if (angle > startAngle) { extremity[0] = Math.cos(angle) * r + x; extremity[1] = Math.sin(angle) * r + y; vec2.min(min, extremity, min); vec2.max(max, extremity, max); } } } } export {ComputeBoundingBox}; Zondy.LevelRenderer.Tool.ComputeBoundingBox = ComputeBoundingBox;