Arc subdivision algorithm

2019-07-23 15:57发布

问题:

I'm looking to sample from a texture along a circular arc in a fragment shader. That kind of rules out recursive methods such as this.

I have come up with a few different ways to accomplish this: Two that seem the most reasonable are (Given start position p, center c, radius r = length(c-p), angle (arc extent) theta in radians and N positions):

1) Rotate the vector p-c about c by theta/N, N times: This requires the construction of a rotation matrix which will be repeatedly used: cost is two trig functions, N 2x2 matrix multiplies, N or so vector subtractions

2) Find the chord length of one segment traversing a sector: Its length is 2*r*sin(theta/2). Once I have the first vector I can rotate it and add it to the previous position to "step along" my arc. The problem with this method is that I still don't know the expression to obtain the orientation of my length 2*r*sin(theta/2) vector. Even if I did I'd likely need trig functions to construct it. I still need to rotate it so that might require me to still build a rotation matrix. Ugh.

Are there other methods I could consider?

回答1:

I think that once you start using circles and angles you are bound to have a couple of trig calls. Given that, the first method seems OK. I'd only note that I do not see the need for 2D matrix multiplies as such if act iteratively on the points.

void f(float cx, float cy, float px, float py, float theta, int N)
{
    float dx = px - cx;
    float dy = py - cy;
    float r2 = dx * dx + dy * dy;
    float r = sqrt(r2);
    float ctheta = cos(theta/(N-1));
    float stheta = sin(theta/(N-1));
    std::cout << cx + dx << "," << cy + dy << std::endl;
    for(int i = 1; i != N; ++i)
    {
        float dxtemp = ctheta * dx - stheta * dy;
        dy = stheta * dx + ctheta * dy;
        dx = dxtemp;
        std::cout << cx + dx << "," << cy + dy << std::endl;
    }
}

Given large N, you might find that some errors accumulate here. Given some assumptions around N and theta you might be able to make some small angle approximations for the trig.

Summary: If you want the specified number of points and are using arcs, I cannot see that you are really going to find a way to do much less computation than something close to option 1).