使用三角函数绘制通过圆的等距平行线

Using Trigonometry to draw equidistant parralleles lines through a circle

如图所示,我需要一个数学公式来计算红色圆点与笛卡尔坐标的等距线。 我猜这不是简单的三角函数...

我的目标是能够计算半个圆周围的笛卡尔点并从中追踪我的线。

使用 p5js,我将使用来自 Perlin 噪声的随机值将其与 sin 或 cos(无论...)混合以从这些点追踪我的线。一开始这是一个数学问题,剩下的对我来说应该很容易,因为我已经有了一个很好的基础,但需要用这个数学来优化。

有什么线索吗?

这是一个角度(极坐标)和笛卡尔坐标之间的转换问题。

这里是一个函数calculateLines(x, y, radius, dist, angle, shift),它取圆心坐标、圆半径、直线之间的距离、直线的角度(以弧度为单位)和直线的位移(垂直于它们的方向)。它 returns 一个带有段的数组。一个段由一对坐标决定,即[x1, y1, x2, y2].

下面的代码片段允许您使用这些参数并以交互方式查看结果:

function calculateSegments(x, y, radius, dist, angle, shift=0) {
    let segments = [];
    for (let step = shift - Math.floor((radius + shift) / dist) * dist; step < radius; step += dist) {
        let polar = Math.acos(step / radius);
        let segment = [
            x + Math.cos(angle + polar) * radius,
            y + Math.sin(angle + polar) * radius,
            x + Math.cos(angle - polar) * radius,
            y + Math.sin(angle - polar) * radius
        ];
        segments.push(segment);
    }
    return segments;
}

// I/O management:

let [inpRadius, inpDistance, inpAngle, inpShift] = document.querySelectorAll("input");

document.addEventListener("input", refresh);

let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
let cx = canvas.width >> 1;
let cy = canvas.height >> 1;

function drawCircle(x, y, r) {
    ctx.beginPath();
    ctx.arc(x, y, r, 0, 2 * Math.PI, false);
    ctx.stroke();
}

function drawSegment([x1, y1, x2, y2]) {
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.stroke();
}

function clear() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
}

function refresh() {
    // Get current input
    let radius = Math.max(1, +inpRadius.value); // sanitise input
    let distance = Math.max(1, +inpDistance.value);
    let angle = +inpAngle.value * Math.PI / 180; // convert to radians
    let shift = +inpShift.value;
    
    // Perform the calculation
    let segments = calculateSegments(cx, cy, radius, distance, angle, shift);

    // Display result
    clear();
    drawCircle(cx, cy, radius);
    segments.forEach(drawSegment);
}

refresh();
input { width: 5em }
canvas { background: #eee }
<div style="float: left">
Radius of circle: <input type="number" id="radius" value="50" min="1"><br>
Distance between lines: <input type="number" id="distance" value="14" min="1"><br>
Angle of lines (degrees): <input type="number" id="angle" value="120"><br>
Shift: <input type="number" id="shift" value="0"><br>
</div>
<canvas width="180" height="180"></canvas>

鉴于:

(x_cntr, y_cntr) = the center of the circle, 
radius = radius of the circle, 
dist = distance between lines, 
angle = angle of lines relative to the horizontal Ox axis, 
offset = distance of first line from the border of the circle:

这是另一个可以完成这项工作的函数。这种方法试图避免在循环中使用余弦和反正弦进行昂贵的计算,并仅用一次昂贵的 sqrt 计算来代替它们。其余的是简单的算术运算(例如乘法和加法)。这个想法是通过给定半径的圆并以原点 (0,0) 为中心计算等距水平线 运行 的简单规范情况下的点的位置,然后旋转和平移坐标以线应相对于水平轴 Ox 定义的角度拟合实际圆边界的点。

function get_points(x_cntr, y_cntr, radius, dist, angle, offset) {
    let list_of_points = [];
    let n = Math.floor( (2 * radius - offset) / dist ) + 1;
    let cos_angle = Math.cos(angle); 
    let sin_angle = Math.sin(angle);
    for (let m = 0; m < n; m = m+1) {
      let y = offset + m * dist - radius;
      let x = Math.sqrt(radius*radius - y*y);
      let point = [
          x_cntr + cos_angle * x - sin_angle * y,
          y_cntr + sin_angle * x + cos_angle * y
          ]
      list_of_points.push(point);
   }
   return list_of_points;
}