2013-04-11 85 views
9

我一直在這工作了好幾個星期,但一直無法讓我的算法正常工作,我在我的智慧結束。下面是我所取得的成就的說明:在B樣條上實現De Boors算法尋找點

enter image description here

如果一切工作我希望在結束一個完美的圓/橢圓形。

每添加一個新的控制點(黃色),我的採樣點(白色)都會重新計算。在4個控制點上,一切看起來都很完美,再一次在第一個東西的後面加上第五個東西,但是第六個東西在第六個時候開始偏離了第七個東西,然後在第七個東西上跳起來!

下面我會發布我的代碼,其中calculateWeightForPointI包含實際的算法。如果有人可以找我,我會非常感激。

void updateCurve(const std::vector<glm::vec3>& controls, std::vector<glm::vec3>& samples) 
{ 
    int subCurveOrder = 4; // = k = I want to break my curve into to cubics 

    // De boor 1st attempt 
    if(controls.size() >= subCurveOrder) 
    { 
     createKnotVector(subCurveOrder, controls.size()); 
     samples.clear(); 

     for(int steps=0; steps<=20; steps++) 
     { 
      // use steps to get a 0-1 range value for progression along the curve 
        // then get that value into the range [k-1, n+1] 
      // k-1 = subCurveOrder-1 
      // n+1 = always the number of total control points 

      float t = (steps/20.0f) * (controls.size() - (subCurveOrder-1)) + subCurveOrder-1; 

      glm::vec3 newPoint(0,0,0); 
      for(int i=1; i <= controls.size(); i++) 
      { 
       float weightForControl = calculateWeightForPointI(i, subCurveOrder, controls.size(), t); 
       newPoint += weightForControl * controls.at(i-1); 
      } 
      samples.push_back(newPoint); 
     } 
    } 

} 

    //i = the weight we're looking for, i should go from 1 to n+1, where n+1 is equal to the total number of control points. 
    //k = curve order = power/degree +1. eg, to break whole curve into cubics use a curve order of 4 
    //cps = number of total control points 
    //t = current step/interp value 
float calculateWeightForPointI(int i, int k, int cps, float t) 
    { 
     //test if we've reached the bottom of the recursive call 
     if(k == 1) 
     { 
      if(t >= knot(i) && t < knot(i+1)) 
       return 1; 
      else 
       return 0; 
     } 

     float numeratorA = (t - knot(i)); 
     float denominatorA = (knot(i + k-1) - knot(i)); 
     float numeratorB = (knot(i + k) - t); 
     float denominatorB = (knot(i + k) - knot(i + 1)); 

     float subweightA = 0; 
     float subweightB = 0; 

     if(denominatorA != 0) 
      subweightA = numeratorA/denominatorA * calculateWeightForPointI(i, k-1, cps, t); 
     if(denominatorB != 0) 
      subweightB = numeratorB/denominatorB * calculateWeightForPointI(i+1, k-1, cps, t); 

     return subweightA + subweightB; 

    } 

    //returns the knot value at the passed in index 
    //if i = 1 and we want Xi then we have to remember to index with i-1 
float knot(int indexForKnot) 
    { 
     // When getting the index for the knot function i remember to subtract 1 from i because of the difference caused by us counting from i=1 to n+1 and indexing a vector from 0 
     return knotVector.at(indexForKnot-1); 
    } 
    //calculate the whole knot vector 
void createKnotVector(int curveOrderK, int numControlPoints) 
    { 
     int knotSize = curveOrderK + numControlPoints; 
     for(int count = 0; count < knotSize; count++) 
     { 
      knotVector.push_back(count); 
     } 
    } 
+0

http://chi3x10.wordpress.com/2009/10/18/de-boor-algorithm-in-c/你可以得到一點幫助 – Saqlain 2013-04-11 09:13:55

+0

B樣條表現出的凸包屬性。如果你從每個連續的控制點畫出一條線,你會得到一個凸多邊形嗎?它看起來像一些邊相交。 – 2013-04-11 15:21:18

+0

@BrettHale恐怕我不太關注?我現在只是在2D中工作,但是我的B-sline曲線的邊緣(如白點所定義的)沒有任何邊緣似乎相交。哦,等待我們談論控制點重疊嗎?這是故意的,第5,第6和第7點在第1,第2和第3點重疊時試圖繪製一個圓圈。感謝您花時間幫我解決這個問題,我真的很掙扎。 – Holly 2013-04-11 19:17:31

回答

2

您的算法似乎適用於我嘗試過的任何輸入。你的問題可能是一個控制點不是它應該在的地方,或者它們沒有被正確初始化。它看起來像有兩個控制點,低於左下角的一半高度。

Correct Wrong