UNPKG

edeap

Version:

Euler Diagrams Drawn with Ellipses Area-Proportionally (Edeap)

114 lines (113 loc) 3.67 kB
export function toRadians(x) { return (x * Math.PI) / 180; } export function toDegrees(x) { return (x * 180) / Math.PI; } export function ellipseBoundaryPosition(eA, eB, eR, angleRad) { const divisor = Math.sqrt(Math.pow(eB * Math.cos(angleRad), 2) + Math.pow(eA * Math.sin(angleRad), 2)); let y = (eA * eB * Math.sin(angleRad)) / divisor; let x = (eA * eB * Math.cos(angleRad)) / divisor; /* let x = (eA * eB) / Math.sqrt(Math.pow(eB, 2) + Math.pow(eA, 2) * Math.pow(Math.tan(angleRad), 2)); if (angleRad < Math.PI * 1.5 && angleRad >= Math.PI/2) { x *= -1; } let y = Math.sqrt(1 - Math.pow(x/eA, 2)) * eB; if (angleRad < Math.PI) { y *= -1; } if (isNaN(x)) { console.log("NAN X: " + eA + ", " + eB + ", " + eR); } if (isNaN(y)) { console.log("NAN X: " + eA + ", " + eB + ", " + eR); } */ if (eR > 0) { const s = Math.sin(eR); const c = Math.cos(eR); const newX = x * c - y * s; const newY = x * s + y * c; x = newX; y = newY; } return { x, y, }; } // Given an x and y position and an ellipse, this function returns // a boolean denoting whether the point lies inside the ellipse. // // Parameters: // x The x position of the point to test. // y The y position of the point to test. // cx The center x position of the ellipse. // cy The center y position of the ellipse. // rx The x radius of the ellipse. // ry The y radius of the ellipse. // rot The rotation of the ellipse in radians. // // Based on mathematics described on this page: // https://stackoverflow.com/questions/7946187/point-and-ellipse-rotated-position-test-algorithm // export function isInEllipse(x, y, cx, cy, rx, ry, rot) { const bigR = Math.max(rx, ry); if (x < cx - bigR || x > cx + bigR || y < cy - bigR || y > cy + bigR) { // Outside bounding box estimation. return false; } const dx = x - cx; const dy = y - cy; const cos = Math.cos(rot); const sin = Math.sin(rot); const dd = rx * rx; const DD = ry * ry; const cosXsinY = cos * dx + sin * dy; const sinXcosY = sin * dx - cos * dy; const ellipse = (cosXsinY * cosXsinY) / dd + (sinXcosY * sinXcosY) / DD; return ellipse <= 1; } // Given an ellipse this function returns the bounding box as // and object. // // Parameters: // cx The center x position of the ellipse. // cy The center y position of the ellipse. // rx The x radius of the ellipse. // ry The y radius of the ellipse. // rot The rotation of the ellipse in radians. // // Return value: // An object with a p1 and p2 property where each is a point // object with an x and y property. // // Based on mathematics described on this page: // https://math.stackexchange.com/questions/91132/how-to-get-the-limits-of-rotated-ellipse // export function ellipseBoundingBox({ X: cx, Y: cy, A: rx, B: ry, R: rot, }) { const acos = rx * Math.cos(rot); const bsin = ry * Math.sin(rot); const xRes = Math.sqrt(acos * acos + bsin * bsin); const asin = rx * Math.sin(rot); const bcos = ry * Math.cos(rot); const yRes = Math.sqrt(asin * asin + bcos * bcos); return { p1: { x: cx - xRes, y: cy - yRes, }, p2: { x: cx + xRes, y: cy + yRes, }, }; } // Compute the distance between two points in the plane. export function distanceBetween(x1, y1, x2, y2) { // Pythagoras: A^2 = B^2 + C^2 return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); }