Search code examples
geometrycoordinatescomputational-geometrycoordinate-transformationpolar-coordinates

Project 2D points onto Circle/Curve


I have a list of XY points which represent text in a "dot matrix" form. The origin of the first point in the set in the set is 0,0(upper left point). (I can change the points to incremental coordinates too)

I would like to project or wrap the points around a radius like so: enter image description here

I've tried to follow this answer, but the results are not what I expect: How To Project Point Onto a Sphere

I've also tried converting to Polar coordinates and imposing the R coordinate to determine the Theta and the convert back to cartesian, but that does not work either.

For example, the letter T produces this which should then be projected to the curve:

0, .0
0.1, .0
0.2, .0
0.2, .-0.1
0.2, .-0.2
0.2, .-0.3
0.2, .-0.4
0.2, .-0.5
0.2, .-0.6
0.3, .0
0.4, .0

What is the process to get my points to follow a radial curve


Solution

  • Say you want to curve around a circle centered at (cx, cy) with radius r, using dots with size (diameter) 0.1.

    The distance, d the center of a dot at (x, y) is from center of the circle is:

    d = r + y - size / 2

    (I've subtracted size / 2 to get the position of the center of dot)

    The angle theta (in radians) around the circle is:

    theta = (x + size / 2) / r

    The position of the dot is then:

    dx = cx + d * cos(theta) dy = cy - d * sin(theta)

    Here's an example using SVG and Javascript

    var svg = document.getElementById('curve-text');
    var NS = "http://www.w3.org/2000/svg";
    
    var points = [
        [0, 0],
        [0.1, 0],
        [0.2, 0],
        [0.2, -0.1],
        [0.2, -0.2],
        [0.2, -0.3],
        [0.2, -0.4],
        [0.2, -0.5],
        [0.2, -0.6],
        [0.3, 0],
        [0.4, 0]
    ];
    
    var cx = 2;
    var cy = 2;
    var r = 2;
    var size = 0.1;
    
    drawCircle(cx, cy , r - 0.7);
    
    var circumference = Math.PI * 2 * r;
    var angle = 360 / circumference;
    var radians = 1 / r;
    
    // Add 12 copies of the letter T around the circle
    for (var j = 0; j < 12; j++) {
        for (var i = 0; i < points.length; i++) {
            addDots(points[i][0] + j, points[i][1], size, cx, cy, r)
        }
    }
    
    function drawCircle(cx, cy , r) {
        var circle = document.createElementNS(NS, 'circle');
        circle.setAttributeNS(null, 'cx', cx);
        circle.setAttributeNS(null, 'cy', cy);
        circle.setAttributeNS(null, 'r', r);
        circle.setAttributeNS(null, 'fill', 'none');
        circle.setAttributeNS(null, 'stroke', 'black');
        circle.setAttributeNS(null, 'stroke-width', '0.02');
        svg.appendChild(circle);
    }
    
    function addDots(x, y, size, cx, cy, r) {
        var dotR = size / 2;
        var d = r + (y - dotR);
        var theta = (x + dotR) / r;
    
        var x = cx + d * Math.cos(theta);
        var y = cy - d * Math.sin(theta);
    
        var dot = document.createElementNS(NS, 'circle');
        dot.setAttributeNS(null, 'cx', x);
        dot.setAttributeNS(null, 'cy', y);
        dot.setAttributeNS(null, 'r', dotR);
        svg.appendChild(dot);
    }
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 4" id="curve-text" width="200" height="200">
    </svg>