Skip to content

Using Trigonometry to draw equidistant parralleles lines through a circle

enter image description here

As seen on the picture, I need a math formula that calculate the red circled point with cartesian coordonate that will make equidistant lines. It is not simple trigonometry I guess…

My goal is to be able to calculate cartesian point around half of the circle and trace my lines from it.

Using p5js, I’ll use random value from Perlin noise mixing it with sin or cos (whatever…) to trace my lines from those points. At start it’s a math problem, the rest should be pretty easy for me since I already have a good base that work, but need to be optimized with this math.

Any clue ?

Answer

This is a matter of converting between angles (polar coordinates) and Cartesian coordinates.

Here is a function calculateLines(x, y, radius, dist, angle, shift) that takes the coordinate of the center, the radius of the circle, the distance between the lines, the angle of the lines (in radians), and the shift of the lines (perpendicular to their direction). It returns an array with segments. A segment is determined by a pair of coordinates, i.e. [x1, y1, x2, y2].

The below snippet allows you to play with these parameters and see the result interactively:

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>