/** * INTERSEC ********************************************************* * @licstart The following is the entire license notice for the * JavaScript code in this page. * * Copyright (C) 2021 Ophir LOJKINE * * * The JavaScript code in this page is free software: you can * redistribute it and/or modify it under the terms of the GNU * General Public License (GNU GPL) as published by the Free Software * Foundation, either version 3 of the License, or (at your option) * any later version. The code is distributed WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. * * As additional permission under GNU GPL version 3 section 7, you * may distribute non-source (e.g., minimized or compacted) forms of * that code without the copy of the GNU GPL normally required by * section 4, provided you include this license notice and a URL * through which recipients can access the Corresponding Source. * * @licend */ if ( !SVGGraphicsElement.prototype.transformedBBox || !SVGGraphicsElement.prototype.transformedBBoxContains ) { [pointInTransformedBBox, transformedBBoxIntersects] = (function () { var get_transform_matrix = function (elem) { // Returns the first translate or transform matrix or makes one var transform = null; for (var i = 0; i < elem.transform.baseVal.numberOfItems; ++i) { var baseVal = elem.transform.baseVal[i]; // quick tests showed that even if one changes only the fields e and f or uses createSVGTransformFromMatrix // the brower may add a SVG_TRANSFORM_MATRIX instead of a SVG_TRANSFORM_TRANSLATE if (baseVal.type === SVGTransform.SVG_TRANSFORM_MATRIX) { transform = baseVal; break; } } if (transform == null) { transform = elem.transform.baseVal.createSVGTransformFromMatrix( Tools.svg.createSVGMatrix(), ); elem.transform.baseVal.appendItem(transform); } return transform.matrix; }; var transformRelative = function (m, t) { return [m.a * t[0] + m.c * t[1], m.b * t[0] + m.d * t[1]]; }; var transformAbsolute = function (m, t) { return [m.a * t[0] + m.c * t[1] + m.e, m.b * t[0] + m.d * t[1] + m.f]; }; SVGGraphicsElement.prototype.transformedBBox = function (scale = 1) { bbox = this.getBBox(); tmatrix = get_transform_matrix(this); tmatrix.e /= scale; tmatrix.f /= scale; return { r: transformAbsolute(tmatrix, [bbox.x / scale, bbox.y / scale]), a: transformRelative(tmatrix, [bbox.width / scale, 0]), b: transformRelative(tmatrix, [0, bbox.height / scale]), }; }; SVGSVGElement.prototype.transformedBBox = function (scale = 1) { bbox = { x: this.x.baseVal.value, y: this.y.baseVal.value, width: this.width.baseVal.value, height: this.height.baseVal.value, }; tmatrix = get_transform_matrix(this); tmatrix.e /= scale; tmatrix.f /= scale; return { r: transformAbsolute(tmatrix, [bbox.x / scale, bbox.y / scale]), a: transformRelative(tmatrix, [bbox.width / scale, 0]), b: transformRelative(tmatrix, [0, bbox.height / scale]), }; }; var pointInTransformedBBox = function ([x, y], { r, a, b }) { var d = [x - r[0], y - r[1]]; var idet = a[0] * b[1] - a[1] * b[0]; var c1 = (d[0] * b[1] - d[1] * b[0]) / idet; var c2 = (d[1] * a[0] - d[0] * a[1]) / idet; return c1 >= 0 && c1 <= 1 && c2 >= 0 && c2 <= 1; }; SVGGraphicsElement.prototype.transformedBBoxContains = function (x, y) { return pointInTransformedBBox([x, y], this.transformedBBox()); }; function transformedBBoxIntersects(bbox_a, bbox_b) { var corners = [ bbox_b.r, [bbox_b.r[0] + bbox_b.a[0], bbox_b.r[1] + bbox_b.a[1]], [bbox_b.r[0] + bbox_b.b[0], bbox_b.r[1] + bbox_b.b[1]], [ bbox_b.r[0] + bbox_b.a[0] + bbox_b.b[0], bbox_b.r[1] + bbox_b.a[1] + bbox_b.b[1], ], ]; return corners.every(function (corner) { return pointInTransformedBBox(corner, bbox_a); }); } SVGGraphicsElement.prototype.transformedBBoxIntersects = function (bbox) { return transformedBBoxIntersects(this.transformedBBox(), bbox); }; return [pointInTransformedBBox, transformedBBoxIntersects]; })(); }