计算Cox De Boor算法的结矢量的正确方法是什么?

时间:2012-05-28 09:32:40

标签: ios bezier curve

我目前正在尝试使用Cox De Boor算法绘制贝塞尔曲线。我已经设法生成一些可接受的东西,具有设定度,控制点数和预定义的结矢量,但我想调整我的代码,以便它可以在给定任意数量的控制点和任何程度的情况下运行。我90%肯定我当前遇到的问题,即路径徘徊到0/0点,是由于我没有正确计算结矢量。如果有人能给我一两个提示,我将不胜感激。请注意,我目前正在单独计算每个维度(在这种情况下只是x和y);我将最终调整此代码以对所有维度使用相同的预先计算。我也可能将它调整为使用C数组而不是NSArrays,但从我所看到的情况来看,没有真正的速度优势。

我目前使用5个控制点产生3度曲线,结点矢量为{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;
}

1 个答案:

答案 0 :(得分:0)

没关系,我找到了这个非常有用的网页: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/INT-APP/PARA-knot-generation.html

因此,任何有相同问题的人都可以使用以下方法生成一个合适的结矢量,其中'controls'是影响线段的控制点的数量,'degree'是...嗯,程度曲线!不要忘记,度数不能等于或超过曲线中控制点的数量:

- (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;    
}