Как правильно вычислить вектор узла для алгоритма Кокса Де Бура?

В настоящее время я пытаюсь реализовать алгоритм Кокса Де Бура для рисования кривых Безье. Мне удалось создать что-то приемлемое с заданной степенью, количеством контрольных точек и предопределенным вектором узла, но я хочу адаптировать свой код, чтобы он функционировал при любом количестве контрольных точек и любой степени. Я на 90% уверен, что проблемы, с которыми я сталкиваюсь в настоящее время, то есть то, что путь уходит в точку 0/0, связаны с тем, что я неправильно рассчитываю векторы узлов. Если кто-нибудь может дать мне подсказку или два, я был бы признателен. Обратите внимание, что в настоящее время я вычисляю каждое измерение (в данном случае только x и y) по отдельности; Со временем я адаптирую этот код, чтобы использовать одни и те же предварительные вычисления для всех измерений. Я также могу настроить его для использования массивов C, а не NSArrays, но из того, что я видел, в этом нет реального преимущества в скорости.

В настоящее время я создаю кривую степени 3, используя 5 контрольных точек с вектором узла {0, 0, 0, 0, 1, 2, 2, 2, 2}.

- (double) coxDeBoorForDegree:(NSUInteger)degree span:(NSUInteger)span travel:(double)travel knotVector:(NSArray *)vector
{
    double k1 = [[vector objectAtIndex:span] doubleValue];
    double k2 = [[vector objectAtIndex:span+1] doubleValue];
    if (degree == 1) {
        if (k1 <= travel && travel <= k2) return 1.0;
        return 0.0;
    }

    double k3 = [[vector objectAtIndex:span+degree-1] doubleValue];
    double k4 = [[vector objectAtIndex:span+degree] doubleValue];
    double density1 = k3 - k1;
    double density2 = k4 - k2;
    double equation1 = 0.0, equation2 = 0.0;

    if (density1 > 0.0) equation1 = ((travel-k1) / density1) * [self coxDeBoorForDegree:degree-1 span:span travel:travel knotVector:vector];
    if (density2 > 0.0) equation2 = ((k4-travel) / density2) * [self coxDeBoorForDegree:degree-1 span:span+1 travel:travel knotVector:vector];

    return equation1 + equation2;
}



- (double) valueAtTravel:(double)travel degree:(NSUInteger)degree points:(NSArray *)points knotVector:(NSArray *)vector
{
    double total = 0.0;
    for (NSUInteger i = 0; i < points.count; i++) {
        float weight = [self coxDeBoorForDegree:degree+1 span:i travel:travel knotVector:vector];
        if (weight > 0.001) total += weight * [[points objectAtIndex:i] doubleValue];
    }
    return total;
}

person Ash    schedule 28.05.2012    source источник


Ответы (1)


Неважно, я нашел эту очень полезную веб-страницу: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/INT-APP/PARA-knot-generation.html

Следовательно, любой, у кого есть та же проблема, может использовать следующий метод для создания подходящего вектора узла, где «управление» — это количество контрольных точек, влияющих на сегмент линии, а «степень» — это... ну, степень кривой! Не забывайте, что степень не может быть равна или превышать количество контрольных точек на кривой:

- (NSArray *) nodeVectorForControlCount:(NSUInteger)controls degree:(NSUInteger)degree
{    
    NSUInteger knotIncrement = 0;
    NSUInteger knotsRequired = controls + degree + 1;
    NSMutableArray *constructor = [[NSMutableArray alloc] initWithCapacity:knotsRequired];
    for (NSUInteger i = 0; i < knotsRequired; i++) {
        [constructor addObject:[NSNumber numberWithDouble:(double)knotIncrement]];
        if (i >= degree && i < controls) knotIncrement++;
    }

    NSArray * returnArray = [NSArray arrayWithArray:constructor];
    [constructor release];
    return returnArray;    
}
person Ash    schedule 28.05.2012