UNPKG

grommet

Version:

focus on the essential experience

162 lines (152 loc) 8.12 kB
"use strict"; exports.__esModule = true; exports.wedgeCommands = exports.translateEndAngle = exports.polarToCartesian = exports.lineCommands = exports.calcAngle = exports.baseUnit = exports.arcCommands = void 0; var POST_DECIMAL_DIGITS = 10; var baseUnit = exports.baseUnit = 24; var polarToCartesian = exports.polarToCartesian = function polarToCartesian(centerX, centerY, radius, angleInDegrees) { var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0; return { x: centerX + radius * Math.cos(angleInRadians), y: centerY + radius * Math.sin(angleInRadians) }; }; var intersection = function intersection(line1Point1, line1Point2, line2Point1, line2Point2) { var x1 = line1Point1.x, y1 = line1Point1.y; var x2 = line1Point2.x, y2 = line1Point2.y; var x3 = line2Point1.x, y3 = line2Point1.y; var x4 = line2Point2.x, y4 = line2Point2.y; // Calculate the denominator var denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); // Check if lines are parallel (denominator is 0) if (Math.abs(denominator) < 1e-10) { return null; // Lines are parallel or coincident } // Calculate the intersection point var t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denominator; var u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denominator; // Calculate intersection coordinates var intersectionX = x1 + t * (x2 - x1); var intersectionY = y1 + t * (y2 - y1); return { x: intersectionX, y: intersectionY, // Optional: check if intersection is within line segments withinSegment1: t >= 0 && t <= 1, withinSegment2: u >= 0 && u <= 1 }; }; var lineCommands = exports.lineCommands = function lineCommands(centerX, centerY, radius, angle) { var start = polarToCartesian(centerX, centerY, radius, angle); var d = ['M', centerX.toFixed(POST_DECIMAL_DIGITS), centerY.toFixed(POST_DECIMAL_DIGITS), 'L', start.x.toFixed(POST_DECIMAL_DIGITS), start.y.toFixed(POST_DECIMAL_DIGITS)].join(' '); return d; }; var arcCommands = exports.arcCommands = function arcCommands(centerX, centerY, radius, startAngle, endAngle) { // handle that we can't draw a complete circle var normalizedEndAngle = endAngle; /* added endAngle - startAngle >= 360 for SemiCircle the endAngle will never be greater then startAngle since it starts with a startAngle of 270. */ if (endAngle > startAngle && endAngle - startAngle >= 360) { normalizedEndAngle = startAngle + 359.99; } var start = polarToCartesian(centerX, centerY, radius, normalizedEndAngle); var end = polarToCartesian(centerX, centerY, radius, startAngle); var arcSweep = normalizedEndAngle - startAngle <= 180 ? '0' : '1'; var d = ['M', start.x.toFixed(POST_DECIMAL_DIGITS), start.y.toFixed(POST_DECIMAL_DIGITS), 'A', radius.toFixed(POST_DECIMAL_DIGITS), radius.toFixed(POST_DECIMAL_DIGITS), 0, arcSweep, 0, end.x.toFixed(POST_DECIMAL_DIGITS), end.y.toFixed(POST_DECIMAL_DIGITS)].join(' '); return d; }; var calcAngle = exports.calcAngle = function calcAngle(radius, angle, midAngle, gap) { if (gap === 0) { return angle; } var gapAngleRadians = Math.asin(Math.abs(gap) / radius); var gapAngle = gapAngleRadians * 180 / Math.PI; return gap > 0 ? Math.min(angle + gapAngle, midAngle) : Math.max(angle - gapAngle, midAngle); }; var gapPoints = function gapPoints(centerX, centerY, outerRadius, innerRadius, angle, midAngle, gap) { var outerAngle = calcAngle(outerRadius, angle, midAngle, gap); var outer = polarToCartesian(centerX, centerY, outerRadius, outerAngle); var inner; if (innerRadius > 0) { var innerAngle = calcAngle(innerRadius, angle, midAngle, gap); inner = polarToCartesian(centerX, centerY, innerRadius, innerAngle); } else { inner = polarToCartesian(centerX, centerY, Math.abs(gap), gap < 0 ? angle - 90 : angle + 90); } return { outer: outer, inner: inner }; }; var wedgeCommands = exports.wedgeCommands = function wedgeCommands(centerX, centerY, outerRadius, innerRadius, startAngle, endAngle, startGap, endGap, startRound, endRound, startRoundDirection) { if (startRoundDirection === void 0) { startRoundDirection = 0; } // handle that we can't draw a complete circle var normalizedEndAngle = endAngle; /* added endAngle - startAngle >= 360 for SemiCircle the endAngle will never be greater then startAngle since it starts with a startAngle of 270. */ if (endAngle > startAngle && endAngle - startAngle >= 359.99) { normalizedEndAngle = startAngle + 359.99; } // if we're rounded we need to ajust the start points to // account for a bigger cap radius // add a little bit extra to start to allow for larger rounded inset cap // The extra needed can be calculated by the Pythagorean theorem var thickness = outerRadius - innerRadius; var extraGap = startRound ? Math.sqrt(Math.pow(thickness / 2 + startGap / 4, 2) - Math.pow(thickness / 2, 2)) : 0; // define the angle at the center of the wedge. We can't let the gap // go past this angle. // calculate the angle span between start and end var angleSpan = (endAngle < startAngle ? endAngle + 360 : endAngle) - startAngle; var midAngle = startAngle + angleSpan / 2; var start = gapPoints(centerX, centerY, outerRadius, innerRadius, startAngle, midAngle < startAngle ? midAngle + 360 : midAngle, startGap + extraGap, startRound); var end = gapPoints(centerX, centerY, outerRadius, innerRadius, normalizedEndAngle, midAngle > endAngle ? midAngle - 360 : midAngle, endGap, endRound); var largeAngle = normalizedEndAngle - startAngle > 180; var arcSweep = largeAngle ? '1' : '0'; var innerCapRadius = innerRadius; var innerArcSweep = arcSweep; var middle; if (innerRadius <= 0) { // we're doing a pie wedge innerArcSweep = arcSweep === '0' ? '1' : '0'; if (largeAngle) { // for a large pie wedge it has an inner corner rather // than a point. We need to round the inner corner innerCapRadius = startGap || endGap || 0; } else { // for a small pie wedge we'll make a point in the center middle = intersection(start.outer, start.inner, end.outer, end.inner); } } var capRadius = (outerRadius - innerRadius) / 2; var startCapRadius = capRadius + (startRoundDirection === 0 ? startGap / 2 : 0); var startPoint = middle || start.inner; var endPoint = middle || end.inner; var startCap = startRound ? ['A', startCapRadius.toFixed(POST_DECIMAL_DIGITS), startCapRadius.toFixed(POST_DECIMAL_DIGITS), 0, 0, startRoundDirection, start.outer.x.toFixed(POST_DECIMAL_DIGITS), start.outer.y.toFixed(POST_DECIMAL_DIGITS)] : ['L', start.outer.x.toFixed(POST_DECIMAL_DIGITS), start.outer.y.toFixed(POST_DECIMAL_DIGITS)]; var endCap = endRound ? ['A', capRadius.toFixed(POST_DECIMAL_DIGITS), capRadius.toFixed(POST_DECIMAL_DIGITS), 0, 0, 1, endPoint.x.toFixed(POST_DECIMAL_DIGITS), endPoint.y.toFixed(POST_DECIMAL_DIGITS)] : ['L', endPoint.x.toFixed(POST_DECIMAL_DIGITS), endPoint.y.toFixed(POST_DECIMAL_DIGITS)]; var d = ['M', startPoint.x.toFixed(POST_DECIMAL_DIGITS), startPoint.y.toFixed(POST_DECIMAL_DIGITS)].concat(startCap, ['A', outerRadius.toFixed(POST_DECIMAL_DIGITS), outerRadius.toFixed(POST_DECIMAL_DIGITS), 0, arcSweep, 1, end.outer.x.toFixed(POST_DECIMAL_DIGITS), end.outer.y.toFixed(POST_DECIMAL_DIGITS)], endCap); if (innerRadius > 0 || largeAngle) { // for a donut or a large pie wedge, draw the inner arc d.push('A', innerCapRadius.toFixed(POST_DECIMAL_DIGITS), innerCapRadius.toFixed(POST_DECIMAL_DIGITS), 0, innerArcSweep, 0, start.inner.x.toFixed(POST_DECIMAL_DIGITS), start.inner.y.toFixed(POST_DECIMAL_DIGITS), 'Z' // close the path ); } return d.join(' '); }; /* TranslatedEngAngle will now take the value of the startAngle + anglePer * value and mod by 360. This was added to take account the startAngle not being 0. So no matter the value it will be % 360 to get the correct angle. */ var translateEndAngle = exports.translateEndAngle = function translateEndAngle(startAngle, anglePer, value) { return Math.max(0, startAngle + anglePer * value) % 360; };