Parse
File Parse math.js
This tree is parsed live from the source file.
Classes
-
{{ item.name }}
- {{ key }}
Not Classes
{{ getTree() }}
Comments
{{ getTreeComments() }}
Source
// Solution 2
Number.EPSILON = Math.pow(2, -52);
Math.sign = function(x) {
return ((x > 0) - (x < 0)) || +x;
};
const vectorAngle = (x, y) =>{
// vectorAngle([3, 4], [4, 3]); // 0.283794109208328
Math.acos(
x.reduce((acc, n, i) => acc + n * y[i], 0) /
(Math.hypot(...x) * Math.hypot(...y))
);
}
const applyAngle = function(s) {
let obtuseOffset = 10;
let offset = 20;
// let o1 = getPointOffsetAbsolute(s.position, s.mid, offset, 1)
// let o2 = getPointOffsetAbsolute(s.mid, s.end, offset, 0)
// a.position.copy(o1)
// a.end.copy(o2)
// a.render()
// a.sweepFlag = 1
// a2.sweepFlag = 0
// Calculate a to b through c,
// The +/-result defines the one _upper_ sweep, neg identifies it as the
// _outer_ or obtuse angle of the pair
// ang1 = calculateAngleWithRefWithNeg(s.position, s.end, s.mid)
let ang1 = s.position.protractorAngleTo(s.end, s.mid)
// let ajl = adjustAngleToPreferredRotation(ang1, 180)
let ajl = ang1.protractorRotate(180)
if(ang1 > 180) {
ajl = 360 - ajl
}
// console.log(ajl)
let oa = ang1 < 0? obtuseOffset: 0;
let ob = ang1 > 0? obtuseOffset: 0;
//acute Arc
drawArcThroughPoint(a, s.position, s.end, s.mid, offset + oa)
a.sweepFlag = +(ang1 > 0)
//obtuse
// drawArcThroughPoint(a2, s.position, s.end, s.mid, offset + ob)
}
const drawArcThroughPoint = function(arc, start, end, mid, offset=20) {
let offsetPlus = 0
mid = new Point(mid)
// let o4 = getPointOffsetAbsolute(start, mid, offset + offsetPlus, 1)
// let o3 = getPointOffsetAbsolute(mid, end, offset + offsetPlus, 0)
let o4 = start.interpolateTo(mid, offset + offsetPlus, 1)
let o3 = mid.interpolateTo(end, offset + offsetPlus, 0)
let po4 = new Point(o4)
if(po4.isNaN(true)) { return }
arc.options.rx = arc.options.ry = offset + offsetPlus
arc.position.copy(o4)
arc.end.copy(o3)
arc.render()
}
let quantizeT = function(s, t, rect){
let endX = t.clientX - rect.x
let endY = t.clientY - rect.y
if(s.settings.quantizeTip != undefined) {
endY = quantizeNumber(endY, s.settings.quantizeTip)
endX = quantizeNumber(endX, s.settings.quantizeTip)
}
return [endX, endY]
}
// function distance(xy1, xy2) {
// return Math.sqrt(Math.pow((xy2.x - xy1.x), 2) + Math.pow((xy2.y - xy1.y), 2));
// }
// function distance2D(xy1, xy2) {
// const dx = xy1.x - xy2.x;
// const dy = xy1.y - xy2.y;
// const distance = Math.sqrt(dx * dx + dy * dy);
// return { x: dx, y: dy, distance }
// }
const spotPlacement = function(s, offset) {
let d = distance(s.position, s.end)
offset = offset == undefined ? (d * -.02): offset
let off = findOffsetPoint(s.position, s.end, offset)
c.width = 5
// c.width = 2.5//offset * .25
c.position.set(off)
c.render()
}
function findOffsetPoint(point1, point2, offsetDistance=10) {
// Calculate unit direction vector
const dist = distance(point1, point2);
const ux = (point2.x - point1.x) / dist;
const uy = (point2.y - point1.y) / dist;
// Calculate perpendicular vector
const px = -uy;
const py = ux;
// Calculate midpoint
const mx = (point1.x + point2.x) / 2;
const my = (point1.y + point2.y) / 2;
// Calculate offset point
const cx = mx + offsetDistance * px;
const cy = my + offsetDistance * py;
res = { x: cx, y: cy };
return res
}
// ---
function calculateFirstSegmentOffsetFromEndWithNeg(start, end) {
// Calculate the total distance from start to end
const distanceAB = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
);
// Calculate the length of the first horizontal segment
const d = distanceAB / (1 + Math.sqrt(2));
const dx = end.x - start.x
const dy = end.y - start.y
console.log(dx,dy)
// Calculate the direction factors for x and y dimensions
const directionX = (dx >= 0) ? 1 : -1;
const directionY = (dy >= 0) ? 1 : -1;
// Calculate the offset from end.x
// Here we use directionX to decide whether to add or subtract d from end.x
let offsetX;
if (directionX === 1 && directionY === 1) {
return end.x - d;
}
if (directionX === -1 && directionY === -1) {
return end.x + d;
}
if (directionX === 1 && directionY === -1) {
return end.x - d;
}
if (directionX === -1 && directionY === 1) {
return end.x + d;
}
return offsetX;
}
function calculateFirstSegmentOffsetFromEndWithNegY(start, end, k='y') {
// Calculate the total distance from start to end
const distanceAB = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
);
// Calculate the length of the first segment, which is universal for both x and y dimensions
const d = distanceAB / (1 + Math.sqrt(2));
// Calculate the direction factors for x and y dimensions
const directionX = (end.x - start.x >= 0) ? 1 : -1;
const directionY = (end.y - start.y >= 0) ? 1 : -1;
// Determine the direction for the dimension specified by k
const directionK = (k === 'x') ? directionX : directionY;
// Determine the end value for the dimension specified by k
const endK = end[k];
// Calculate the offset based on direction
const offsetK = directionK === 1 ? (endK - d) : (endK + d);
return offsetK;
}
function calculateFirstSegmentOffsetFromEndA(start, end, outputAngle=90) {
// Calculate the total distance from start to end
const distanceAB = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
);
// Calculate the original line angle
let angleInRadians = Math.atan2(end.y - start.y, end.x - start.x);
// Convert to degrees
let angleInDegrees = angleInRadians * (180 / Math.PI);
// Normalize the angle to between 0 and 360 degrees
angleInDegrees = (angleInDegrees + 360) % 360;
// Calculate the adjusted angle based on the outputAngle
const adjustedAngle = (angleInDegrees + outputAngle) % 360;
// Calculate the length of the first segment based on trigonometry
// Here we assume the angle is with respect to the x-axis.
// You can adjust this based on your application's needs.
const d = distanceAB / (Math.cos(adjustedAngle * (Math.PI / 180)) + Math.sin(adjustedAngle * (Math.PI / 180)));
// Calculate the offset from end.x
const offsetX = end.x - d * Math.cos(angleInDegrees * (Math.PI / 180));
return offsetX;
}
function calculateFirstSegmentOffsetFromEnd(start, end) {
// Calculate the total distance from start to end
const distanceAB = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
);
// Calculate the length of the first horizontal segment
const d = distanceAB / (1 + Math.sqrt(2));
// Calculate the offset from end.x
const offsetX = end.x - d;
return offsetX;
}
function calculateFirstSegmentLength(start, end) {
// Calculate the total distance from start to end
const distanceAB = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
);
// Calculate the length of the first horizontal segment
const d = distanceAB / (1 + Math.sqrt(2));
return d;
}
function quantizeNumber(value, quantize=1) {
const quantizedValue = Math.round(value / quantize) * quantize;
return quantizedValue;
}
function findRadius(pointA, pointB, pointC) {
// // Test the function
// const pointA = { x: 0, y: 0 };
// const pointB = { x: 1, y: 0 };
// const pointC = { x: 0.5, y: 0.5 * Math.sqrt(3) };
// const radius = findRadius(pointA, pointB, pointC);
// console.log("Radius:", radius);
const a = distance(pointB, pointC);
const b = distance(pointC, pointA);
const c = distance(pointA, pointB);
const s = a + b + c; // semi-perimeter
const radius = (a * b * c) / Math.sqrt(s * (s - 2 * a) * (s - 2 * b) * (s - 2 * c));
return radius;
}
// function distance(xy1, xy2) {
// return Math.sqrt(Math.pow((xy2.x - xy1.x), 2) + Math.pow((xy2.y - xy1.y), 2));
// }
// Function to quantize an angle based on the number of divisions (bisect)
function quantizeAngle(inputAngle, bisect) {
/*
// Test the function
console.log(quantizeAngle(10, 4)); // Should return 0
console.log(quantizeAngle(50, 4)); // Should return 90
console.log(quantizeAngle(10, 8)); // Should return 0
console.log(quantizeAngle(50, 8)); // Should return 45
*/
// Normalize the input angle to between 0 and 360 degrees
inputAngle = inputAngle % 360;
if (inputAngle < 0) {
inputAngle += 360;
}
// Calculate the size of each sector
const sectorSize = 360 / bisect;
// Find the closest multiple of sectorSize to inputAngle
const closestAngle = Math.round(inputAngle / sectorSize) * sectorSize;
// Normalize the closest angle to between 0 and 360 degrees
return closestAngle % 360;
}
function calculateAngle(point1, point2) {
/**
// Test the function
const point1 = {x: 10, y: 10};
const point2 = {x: 10, y: 100};
console.log(calculateAngle(point1, point2)); // 90
// GPT
*/
// deltaX and deltaY are the changes in x and y respectively between the two points
const deltaX = point2.x - point1.x;
const deltaY = point2.y - point1.y;
// Calculate the angle in radians and convert it to degrees
let angleInDegrees = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
// Adjust the angle so that "up" corresponds to 0 degrees and "down" corresponds to 180 degrees
angleInDegrees = (angleInDegrees + 360) % 360;
return angleInDegrees;
}
function calculateAngleWithRef(point1, point2, referencePoint) {
// First calculate the "incoming direction" angle using
// point1 and referencePoint
const refDeltaX = point1.x - referencePoint.x;
const refDeltaY = point1.y - referencePoint.y;
let refAngleInDegrees = Math.atan2(refDeltaY, refDeltaX) * (180 / Math.PI);
refAngleInDegrees = (refAngleInDegrees + 360) % 360;
// Then calculate the angle between point1 and point2
const deltaX = point2.x - point1.x;
const deltaY = point2.y - point1.y;
let angleInDegrees = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
angleInDegrees = (angleInDegrees + 360) % 360;
// Finally, find the relative angle
let relativeAngleInDegrees = angleInDegrees - refAngleInDegrees;
// Normalize the relative angle to be between 0 and 360
relativeAngleInDegrees = (relativeAngleInDegrees + 360) % 360;
return relativeAngleInDegrees;
}
function calculateAngleWithRefNegMirror(point1, point2, referencePoint) {
/*
Calculate from a to b through c. with the result always less than 180.
where the real point line would be
point1 --> referencePoint -\
\-> point2
The angle across point1 and 2 is the result.
The line from point1 to referencePoint is known as the 'incoming direction'
*/
// First calculate the "incoming direction" angle using point1 and referencePoint
const refDeltaX = point1.x - referencePoint.x;
const refDeltaY = point1.y - referencePoint.y;
let refAngleInDegrees = Math.atan2(refDeltaY, refDeltaX) * (180 / Math.PI);
refAngleInDegrees = (refAngleInDegrees + 360) % 360;
// Then calculate the angle between point1 and point2
const deltaX = point2.x - point1.x;
const deltaY = point2.y - point1.y;
let angleInDegrees = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
angleInDegrees = (angleInDegrees + 360) % 360;
// Finally, find the relative angle
let relativeAngleInDegrees = angleInDegrees - refAngleInDegrees;
// Normalize the relative angle to be between 0 and 360
relativeAngleInDegrees = (relativeAngleInDegrees + 360) % 360;
// Convert obtuse angles to their acute supplementary angles
if (relativeAngleInDegrees > 180) {
relativeAngleInDegrees = 360 - relativeAngleInDegrees;
}
return relativeAngleInDegrees;
}
function calculateAngleWithRefWithNeg(point1, point2, referencePoint) {
/*
Calculate from a to b through c where the result is >180 for acute, and <180 of abtuse.
This is done in the assumtion a lint to a line is always 180degrees max, therefore
the neg infers the _obtuse_ side of the angle and is `360 + (negativeValue)`.
Where the real point line would be
point1 --> referencePoint -\
\-> point2
The angle across point1 and 2 is the result.
The line from point1 to referencePoint is known as the 'incoming direction'
*/
// First calculate the "incoming direction" angle using point1 and referencePoint
const refDeltaX = point1.x - referencePoint.x;
const refDeltaY = point1.y - referencePoint.y;
let refAngleInDegrees = Math.atan2(refDeltaY, refDeltaX) * (180 / Math.PI);
refAngleInDegrees = (refAngleInDegrees + 360) % 360;
// Then calculate the angle between point1 and point2
const deltaX = point2.x - point1.x;
const deltaY = point2.y - point1.y;
let angleInDegrees = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
angleInDegrees = (angleInDegrees + 360) % 360;
// Finally, find the relative angle
let relativeAngleInDegrees = angleInDegrees - refAngleInDegrees;
// Normalize the relative angle to be between 0 and 360
relativeAngleInDegrees = (relativeAngleInDegrees + 360) % 360;
// Use negative angle for obtuse angles
if (relativeAngleInDegrees > 180) {
relativeAngleInDegrees = relativeAngleInDegrees - 360;
}
return relativeAngleInDegrees;
}
function adjustAngleToPreferredRotation(relativeAngle, preferredRotation) {
// Normalize the relative angle and preferred rotation to be between 0 and 360
relativeAngle = (relativeAngle + 360) % 360;
preferredRotation = (preferredRotation + 360) % 360;
// Calculate the new angle relative to the preferred rotation
let adjustedAngle = preferredRotation - relativeAngle;
// Normalize the adjusted angle to be between 0 and 360
adjustedAngle = (adjustedAngle + 360) % 360;
return adjustedAngle;
}
function findOffsetPoint(point1, point2, offsetDistance=10) {
// Calculate unit direction vector
const dist = distance(point1, point2);
const ux = (point2.x - point1.x) / dist;
const uy = (point2.y - point1.y) / dist;
// Calculate perpendicular vector
const px = -uy;
const py = ux;
// Calculate midpoint
const mx = (point1.x + point2.x) / 2;
const my = (point1.y + point2.y) / 2;
// Calculate offset point
const cx = mx + offsetDistance * px;
const cy = my + offsetDistance * py;
res = { x: cx, y: cy };
return res
}
function getOffsetPoint(pointA, pointB, percentage, fromPoint) {
if (fromPoint === 1) {
[pointA, pointB] = [pointB, pointA];
}
const x = (1 - percentage) * pointA.x + percentage * pointB.x;
const y = (1 - percentage) * pointA.y + percentage * pointB.y;
return { x, y };
}
function getPointOffsetAbsolute(pointA, pointB, distance, fromPoint) {
// Swap points if the offset is from point B
if (fromPoint === 1) {
[pointA, pointB] = [pointB, pointA];
}
// Find the direction vector from pointA to pointB
const dirX = pointB.x - pointA.x;
const dirY = pointB.y - pointA.y;
// Calculate the length of the direction vector
const length = Math.sqrt(dirX * dirX + dirY * dirY);
// Normalize the direction vector
const normX = dirX / length;
const normY = dirY / length;
// Scale the normalized vector by the given distance
const offsetX = normX * distance;
const offsetY = normY * distance;
// Calculate the new point
const x = pointA.x + offsetX;
const y = pointA.y + offsetY;
return { x, y };
}
// const pointA = { x: 0, y: 0 };
// const pointB = { x: 100, y: 100 };
// // Offset 50 units from point A towards point B
// const result1 = getPointOffsetAbsolute(pointA, pointB, 50, 0);
// console.log(result1); // Should output a point approximately at { x: 35.36, y: 35.36 }
// // Offset 50 units from point B towards point A
// const result2 = getPointOffsetAbsolute(pointA, pointB, 50, 1);
// console.log(result2); // Should output a point approximately at { x: 64.64, y: 64.64 }
function linePathArray(start, end, gap = 10, rotation = 0) {
const toRadians = (degrees) => (degrees * Math.PI) / 180;
// Compute the rotation matrix elements
const cosTheta = Math.cos(toRadians(rotation));
const sinTheta = Math.sin(toRadians(rotation));
// Calculate the extra length required to ensure lines span the entire rectangle
const extra = Math.abs((end.y - start.y) * sinTheta) + Math.abs((end.x - start.x) * cosTheta);
// Adjust the start and end x-coordinates
const adjustedStartX = start.x - extra;
const adjustedEndX = end.x + extra;
const numLines = Math.ceil((adjustedEndX - adjustedStartX) / gap);
let pathData = '';
for (let i = 0; i <= numLines; i++) {
// Starting point of each line (before rotation)
const baseX = adjustedStartX + i * gap;
const baseY = start.y;
// Applying rotation to get the end point
const x1 = baseX;
const y1 = baseY;
const x2 = baseX - (end.y - start.y) * sinTheta;
const y2 = baseY + (end.y - start.y) * cosTheta;
// Only add the line segment if it intersects with the rectangle
// (You can further optimize this to compute intersection points if necessary)
if ((x1 >= start.x && x1 <= end.x && y1 >= start.y && y1 <= end.y) ||
(x2 >= start.x && x2 <= end.x && y2 >= start.y && y2 <= end.y)) {
pathData += `M${x1} ${y1} L${x2} ${y2} `;
}
}
return pathData;
}
function linePathArray2(start, end, gap = 10, rotation = 0) {
const toRadians = (degrees) => (degrees * Math.PI) / 180;
function lineIntersectRect(m, c, start, end) {
let left = { x: start.x, y: m * start.x + c };
let right = { x: end.x, y: m * end.x + c };
let top = { x: (start.y - c) / m, y: start.y };
let bottom = { x: (end.y - c) / m, y: end.y };
let points = [left, right, top, bottom];
let validPoints = points.filter(pt => pt.x >= start.x && pt.x <= end.x && pt.y >= start.y && pt.y <= end.y);
validPoints.sort((a, b) => a.x - b.x || a.y - b.y);
if (validPoints.length < 2) return null;
return [validPoints[0], validPoints[validPoints.length - 1]];
}
const m = Math.tan(toRadians(rotation));
const centerX = (start.x + end.x) / 2;
const centerY = (start.y + end.y) / 2;
let pathData = '';
// Draw the central line
let centralC = centerY - m * centerX;
let segment = lineIntersectRect(m, centralC, start, end);
if (segment) {
pathData += `M${segment[0].x} ${segment[0].y} L${segment[1].x} ${segment[1].y} `;
}
// Draw lines outwards from center in both directions
let i = 1;
while (i < 3000) {
const d = gap * i;
let validSegments = 0;
if(validSegments > 500) {
break
}
// Line shifted upwards from the center
let c1 = centerY - m * (centerX - d);
segment = lineIntersectRect(m, c1, start, end);
if (segment) {
validSegments++;
pathData += `M${segment[0].x} ${segment[0].y} L${segment[1].x} ${segment[1].y} `;
}
// Line shifted downwards from the center
let c2 = centerY - m * (centerX + d);
segment = lineIntersectRect(m, c2, start, end);
if (segment) {
validSegments++;
pathData += `M${segment[0].x} ${segment[0].y} L${segment[1].x} ${segment[1].y} `;
}
// If no lines intersected the rectangle, we're done
if (validSegments === 0) break;
i++;
}
return pathData;
}
function linePathArray3(start, end, gap = 10, rotation = 0, offset = 0) {
function rotatePoint(px, py, angle) {
const s = Math.sin(angle);
const c = Math.cos(angle);
return {
x: px * c - py * s,
y: px * s + py * c
};
}
const radianRotation = rotation * (Math.PI / 180);
let pathData = '';
const width = end.x - start.x;
const height = end.y - start.y;
const maxDist = Math.sqrt(width * width + height * height);
const steps = maxDist / gap;
if(typeof(offset) == 'number'){
offset = {x: offset, y: offset}
}
const ofs = function(v) {
let r = (v % ( gap - 2))
return r + 2
}
Object.assign(offset, {
oX: ofs(offset.x)
, oY: ofs(offset.y)
})
// console.log('modOffset', offset.oX)
for (let i = -steps; i <= steps; i++) {
// Get two far away points and then determine where they intersect with our rectangle
let p1 = { x: -maxDist, y: i * gap };
let p2 = { x: maxDist, y: i * gap };
// Rotate the points
p1 = rotatePoint(p1.x, p1.y, radianRotation);
p2 = rotatePoint(p2.x, p2.y, radianRotation);
// Translate them to our rectangle's position
p1.x += ((start.x + end.x) * .5) + offset.oX;
p1.y += ((start.y + end.y) * .5) + offset.oY;
p2.x += ((start.x + end.x) * .5) + offset.oX;
p2.y += ((start.y + end.y) * .5) + offset.oY;
// Now let's determine if these lines actually intersect with our rectangle
// We use a simple clipping algorithm to trim the lines
const clippedLine = clipLineToRect(p1, p2, start, end);
if (clippedLine) {
pathData += `M${clippedLine[0].x} ${clippedLine[0].y} L${clippedLine[1].x} ${clippedLine[1].y} `;
}
}
return pathData;
}
function clipLineToRect(p0, p1, topLeft, bottomRight) {
// Cohen–Sutherland clipping algorithm
const INSIDE = 0;
const LEFT = 1;
const RIGHT = 2;
const BOTTOM = 4;
const TOP = 8;
const computeOutCode = (x, y, topLeft, bottomRight) => {
let code = INSIDE;
if (x < topLeft.x) code |= LEFT;
else if (x > bottomRight.x) code |= RIGHT;
if (y < topLeft.y) code |= TOP;
else if (y > bottomRight.y) code |= BOTTOM;
return code;
};
let outcode0 = computeOutCode(p0.x, p0.y, topLeft, bottomRight);
let outcode1 = computeOutCode(p1.x, p1.y, topLeft, bottomRight);
let accept = false;
while (true) {
if (!(outcode0 | outcode1)) {
accept = true;
break;
} else if (outcode0 & outcode1) {
break;
} else {
let x, y;
const outcodeOut = outcode0 ? outcode0 : outcode1;
if (outcodeOut & TOP) {
x = p0.x + (p1.x - p0.x) * (topLeft.y - p0.y) / (p1.y - p0.y);
y = topLeft.y;
} else if (outcodeOut & BOTTOM) {
x = p0.x + (p1.x - p0.x) * (bottomRight.y - p0.y) / (p1.y - p0.y);
y = bottomRight.y;
} else if (outcodeOut & RIGHT) {
y = p0.y + (p1.y - p0.y) * (bottomRight.x - p0.x) / (p1.x - p0.x);
x = bottomRight.x;
} else if (outcodeOut & LEFT) {
y = p0.y + (p1.y - p0.y) * (topLeft.x - p0.x) / (p1.x - p0.x);
x = topLeft.x;
}
if (outcodeOut === outcode0) {
p0 = { x, y };
outcode0 = computeOutCode(p0.x, p0.y, topLeft, bottomRight);
} else {
p1 = { x, y };
outcode1 = computeOutCode(p1.x, p1.y, topLeft, bottomRight);
}
}
}
if (accept) {
return [p0, p1];
} else {
return null;
}
}
// // Example usage
// const pathData = drawGrid({ x: 300, y: 100 }, { x: 500, y: 300 }, 10, 45);
// console.log(pathData);
function findLineCircleIntersections(p0, p1, cx, cy, radius) {
let dx = p1.x - p0.x;
let dy = p1.y - p0.y;
let A = dx * dx + dy * dy;
let B = 2 * (dx * (p0.x - cx) + dy * (p0.y - cy));
let C = (p0.x - cx) * (p0.x - cx) + (p0.y - cy) * (p0.y - cy) - radius * radius;
let det = B * B - 4 * A * C;
if (det < 0 || A === 0) {
return [];
} else if (det === 0) {
// One solution
let t = -B / (2 * A);
return [{ x: p0.x + t * dx, y: p0.y + t * dy }];
} else {
// Two solutions
let t1 = (-B + Math.sqrt(det)) / (2 * A);
let t2 = (-B - Math.sqrt(det)) / (2 * A);
return [
{ x: p0.x + t1 * dx, y: p0.y + t1 * dy },
{ x: p0.x + t2 * dx, y: p0.y + t2 * dy }
];
}
}
function drawGridInCircle(center, radius, gap, rotation, startOffset) {
let angleRad = (rotation * Math.PI) / 180;
let pathData = "";
// Calculate a distant point based on rotation
let distantPoint = {
x: center.x + 2 * radius * Math.cos(angleRad),
y: center.y + 2 * radius * Math.sin(angleRad)
};
for (let offset = -2 * radius; offset < 2 * radius; offset += gap) {
let start = {
x: center.x + offset * Math.sin(-angleRad),
y: center.y + offset * Math.cos(-angleRad)
};
let end = {
x: start.x + distantPoint.x - center.x,
y: start.y + distantPoint.y - center.y
};
let intersections = findLineCircleIntersections(start, end, center.x, center.y, radius);
if (intersections.length === 2) {
pathData += `M${intersections[0].x} ${intersections[0].y} L${intersections[1].x} ${intersections[1].y} `;
}
}
return pathData.trim();
}
// // Example usage
// const pathData = drawGridInCircle({ x: 400, y: 200 }, 100, 10, 45);
// console.log(pathData);
copy