베 지어 곡선 호 길이


23

참조 : Math.SE에 대한 동일한 질문

베 지어 곡선의 호 길이를 어떻게 찾을 수 있습니까? 예를 들어 선형 베 지어 곡선의 길이는 다음과 같습니다.

length = sqrt(pow(x[1] - x[0], 2) + pow(y[1] - y[0], 2));

그러나 2 차, 3 차 또는 n도 베 지어 곡선은 어떻습니까?

(제 목표는 샘플링 해상도를 미리 추정하는 것이 었으므로 다음 포인트가 이전 포인트에 닿는 지 확인하는 데 시간을 낭비하지 않아도됩니다.)


1
곡선의 길이를 나타내는 질문을 다시 작성해야합니다.
Sparr

나는 수학에 이것을 게시하는 것이 좋습니다, 나는 저기 영리한 얼굴이 당신에게 그들 중 하나가 영리한 웹 글꼴로 답을 줄 것이라고 확신합니다 : p
Tor Valamo

2
@Tor 나는 (어제)했지만 매우 복잡하고 실용적이지 않다고 들었습니다. [ math.stackexchange.com/q/12186/2736 ]
Mateen Ulhaq

천으로 된 곡선 / 스플라인은 베 지어의 대안이며 폐쇄 형 호 길이 표현을 가지고 있지만 이것에 대해서는 아직 많이 알지 못합니다. (곡선을 따라 등거리 점을 생성하려고 시도했습니다.) 카테 너는 닫힌 형태의 호 길이 표현을 가지고 있습니까?
endolith

답변:


9

3 차 베 지어의 간단한 방법은 곡선을 N 개의 세그먼트로 나누고 세그먼트의 길이를 합산하는 것입니다.

그러나 곡선의 일부 길이 만 필요하면 (예 : 길이의 30 %까지) 아크 길이 매개 변수화 가 작동합니다. 간단한 샘플 코드를 사용하여 베 지어에 대한 내 질문 중 하나에 상당히 긴 답변 을 게시 했습니다 .


정말 약한 프로세서 (48Mhz)를 가진 LEGO Mindstorms NXT를 위해이 작업을 수행하고 있으므로 가능한 한 많은 속도가 필요합니다. 몇 가지 속도를 유지하기 위해 분할 방식을 사용하고 (실시간이 아닌 "렌더링을 위해) 충분히 정확할 것입니다. 또한 1.0/t( resolution) 값을 설정할 수있는 옵션이 있으므로 "실시간"(느린 NXT에서 10fps 이상)입니다. 모든 반복 t += resolution및 새로운 점 / 선이 그려집니다. 어쨌든, 아이디어 주셔서 감사합니다.
Mateen Ulhaq

4

이미받은 답변에 동의하고 있지만 베 지어 곡선에 사용할 수있는 간단하지만 강력한 근사 메커니즘을 추가하고 싶습니다. 하위 커브의 기준선에 대한 하위 커브의 일부는 일정한 epsilon 아래 입니다. 이 경우 서브 커브는 기준선에 의해 근사화 될 수 있습니다.

사실, 이것이 그래픽 서브 시스템이 베 지어 곡선을 그릴 때 일반적으로 취하는 접근법이라고 생각합니다. 그러나 이것에 대해 인용하지 마십시오. 현재 언급이 없습니다.

실제로는 다음과 같습니다 : (언어가 관련이없는 것을 제외하고)

public static Line[] toLineStrip(BezierCurve bezierCurve, double epsilon) {
    ArrayList<Line> lines = new ArrayList<Line>();

    Stack<BezierCurve> parts = new Stack<BezierCurve>();
    parts.push(bezierCurve);

    while (!parts.isEmpty()) {
        BezierCurve curve = parts.pop();
        if (distanceToBaseline(curve) < epsilon) {
            lines.add(new Line(curve.get(0), curve.get(1)));
        } else {
            parts.addAll(curve.split(0.5));
        }
    }

    return lines.toArray(new Line[0]);
}

이것이 좋은 접근 방법이지만, 고차 곡선을 더 작은 입방 곡선으로 나누는 또 다른 아이디어가 필요한 고차 베 지어 곡선의 수치 불안정성에 대해 들었습니다.
Mateen Ulhaq

또한 최종 목표가 정확한 추정치 인 경우 곡률이 높은 위치에서 추정치를 과소 평가하지 않도록 선 대신 2 차법으로 근사화하는 것이 좋습니다.
Mateen Ulhaq

2

베 지어 곡선의 호 길이는 선형 및 2 차 곡선의 경우에만 닫힌 형태입니다. 큐빅의 경우 닫힌 솔루션을 보장하지 않습니다. 그 이유는 호 길이가 2 차 다항식에 대해서만 닫힌 근 적분에 의해 정의되기 때문입니다.

참고로 : 점 (a, p) (b, q) 및 (c, r)에 대한 2 차 베 지어의 길이는

(a ^ 2 · (q ^ 2-2 · q · r + r ^ 2) + 2 · a · (r-q) · (b · (p-r) + c · (q-p)) + ( b · (p-r) + c · (q-p)) ^ 2) · LN ((√ (a ^ 2-2 · a · b + b ^ 2 + p ^ 2-2 · p · q + q ^ 2) · √ (a ^ 2 + 2 · a · (c-2 · b) + 4 · b ^ 2-4 · b · c + c ^ 2 + (p-2 · q + r) ^ 2) + a ^ 2 + a · (c-3 · b) + 2 · b ^ 2-b · c + (p-q) · (p-2 · q + r)) / (√ (a ^ 2 + 2 · a · (c-2 · b) + 4 · b ^ 2-4 · b · c + c ^ 2 + (p-2 · q + r) ^ 2) · √ (b ^ 2-2 · b · c + c ^ 2 + q ^ 2-2 · q · r + r ^ 2) + a · (b-c)-2 · b ^ 2 + 3 · b · c-c ^ 2 + (p-2 · q + r) · (q-r))) / (a ​​^ 2 + 2 · a · (c-2 · b) + 4 · b ^ 2-4 · b · c + c ^ 2 + (p-2 · q + r) ^ 2) ^ (3/2) + (√ (a ^ 2-2 · a · b + b ^ 2 + p ^ 2-2 · p · q + q ^ 2) · (a ^ 2 + a · (c-3 · b) + 2 · b ^ 2-b · c + (p-q) · (p-2 · q + r))-√ (b ^ 2-2 · b · c + c ^ 2 + q ^ 2-2 · q · r + r ^ 2) · (a · (b-c)-2 · b ^ 2 + 3 · b · c-c ^ 2 + (p-2 · q + r) · (q-r))) / (a ​​^ 2 + 2 · a · (c-2 · b) + 4 · b ^ 2-4 · b · c + c ^ 2 + (p-2 · q + r) ^ 2)

여기서 LN은 자연 로그이고 ^는 거듭 제곱을 나타내고 √는 제곱근입니다.

따라서 LN의 제곱근은 값 비싼 작업이기 때문에 다각형이나 심슨의 규칙과 같은 통합 체계와 같은 다른 규칙에 의해 아크에 더 쉽고 저렴해야합니다.


2

3 포인트 베 지어 (아래)에 대한 길이의 닫힌 형태 표현을 해결했습니다. 나는 4+ 점에 대해 닫힌 양식을 만들려고 시도하지 않았습니다. 이것은 표현하고 다루기가 어렵거나 복잡 할 것입니다. 그러나 Runge-Kutta 적분 알고리즘과 같은 수치 근사 기법은 호 길이 공식을 사용하여 적분하면 상당히 잘 작동 합니다. MSE 에서 RK45 에 대한 나의 Q & A 는 RK45 구현에 도움이 될 수 있습니다.

여기에 포인트 3 점 베 지어의 아크 길이에 대한 몇 가지 자바 코드입니다 a, b하고 c.

    v.x = 2*(b.x - a.x);
    v.y = 2*(b.y - a.y);
    w.x = c.x - 2*b.x + a.x;
    w.y = c.y - 2*b.y + a.y;

    uu = 4*(w.x*w.x + w.y*w.y);

    if(uu < 0.00001)
    {
        return (float) Math.sqrt((c.x - a.x)*(c.x - a.x) + (c.y - a.y)*(c.y - a.y));
    }

    vv = 4*(v.x*w.x + v.y*w.y);
    ww = v.x*v.x + v.y*v.y;

    t1 = (float) (2*Math.sqrt(uu*(uu + vv + ww)));
    t2 = 2*uu+vv;
    t3 = vv*vv - 4*uu*ww;
    t4 = (float) (2*Math.sqrt(uu*ww));

    return (float) ((t1*t2 - t3*Math.log(t2+t1) -(vv*t4 - t3*Math.log(vv+t4))) / (8*Math.pow(uu, 1.5)));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.