2011-12-01 20 views
6

私は1次元の鳥を持っています。その間隔は浮動小数点です。私は浮動小数点座標の点も持っています。最も近いグリッドポイントまでの距離を見つける必要があります。
例えば:最近点がその背後にあるのでポイントにグリッドの最も近い点を得る

  0.12 
      | 
      * 
|---------|---------|---------|---------|---------| 
0  0.1  0.2  0.3  0.4  0.5 

結果は-0.02あろう。それは

   -0.66 
        | 
        * 
|---------|---------|---------|---------|---------| 
-1  -0.8  -0.6  -0.4  -0.2  0 

た場合
しかし結果は0.06になります。あなたが浮動小数点で見ることができるように、負である可能性があります。
は、私が試した次

float spacing = ...; 
float point = ...; 

while(point >= spacing) point -= spacing; 
while(point < 0) point += spacing; 

if(std::abs(point - spacing) < point) point -= spacing; 

それは動作しますが、私はあなただけの数ラウンドこの使用すべきである

+0

間隔は直線ですか? – GWW

+0

彼の例では線形です。 – GWW

+0

@MooingDuck:その線形、定数(そのパラメータ) – Dani

答えて

6

次のように私たちが最初に左の最寄りのポイントを計算し、右ましょう:

leftBorder = spacing * floor(point/spacing); 
rightBorder = leftBorder + spacing; 

その後距離は簡単です:私たちは最寄りのを見つけることができ、という

if ((point - leftBorder) < (rightBorder - point)) 
    distance = leftBorder - point; 
else 
    distance = rightBorder - point; 

は注意天井単位で点を交互に表示:

rightBorder = spacing * ceil(point/spacing); 
leftBorder = rightBorder - spacing; 
+0

コードの説明を含めてください。 –

+0

提案していただきありがとうございます。私はそれを自己表現的にするために変数を修正しました。もっと説明を付けるべきですか? – petrichor

+0

自然言語で説明するだけであなたの答えが良くなるので、それに行く! –

0

ループのない方法があると確信している:

float spacing = ...; 
float point = ...; 
(point > 0.0) ? floor(point + spacing/2) : ceil(point - spacing/2); 
+0

間隔は一定ではありません。 – Dani

+0

@Dani:非一定の間隔でどのように行うことができるかを明確にしました。 –

+0

床と天井は、最も近いステップ値ではなく、最も近い整数に丸めます。 –

2
std::vector<float> spacing = ...; 
float point = ...; 
float result; 

間隔が(線形)ではないと言うので、合計をキャッシュします。

std::vector<float> sums(1, 0.0); 
float sum=0; 
for(int i=0; i<spacing.size(); ++i) 
    sums.push_back(sum+=spacing[i]); 
//This only needs doing once. 
//sums needs to be in increasing order. 

次に左にポイントを見つけるためにバイナリ検索を実行します。

std::vector<float>::iterator iter; 
iter = std::lower_bound(sums.begin(), sums.end(), point); 

そして、そこから結果を見つける:

if (iter+1 == sums.end()) 
    return point-*iter; 
else { 
    float midpoint = (*iter + *(iter+1))/2; 
    if (point < midpoint) 
     result = point - *iter; 
    else 
     result = *(iter+1) - point; 
} 

を[EDIT]私は愚かな感じしないでください。間隔は一定ではないと言いました。私はこれを非線形と解釈した。しかし、サンプルコード linearです。コンパイル時定数ではありません。私の悪い。私はより一般的な解決策としてこの答えを残しますが、あなたの(線形の)質問はもっと速く解決できます。

+0

間隔は呼び出し内で一定です。呼び出し間で一定ではありません。 – Dani

2

これは私の最初の赤面の試行ですが、これはまったくテストされていないことに注意してください。

float remainder = fmod(point, spacing); // This is the fractional difference of the spaces 
int num_spaces = point/spacing; // This is the number of "spaces" down you are, rounded down 


// If our fractional part is greater than half of the space length, increase the number of spaces. 
// Not sure what you want to do when the point is equidistant to both grid points 
if(remainder > .5 * spacing) 
{ 
    ++num_spaces; 
} 

float closest_value = num_spaces*spacing; 
float distance = closest_value - point; 
+0

答えに対する彼のコメントでは、呼び出し内では一定であると言います。 –

+0

@MooingDuck:いいえ、彼はそれは一定ではないと言います。 – GWW

+0

@MooingDuck:私はその線形ではない、私はちょうど0.1ではないと述べていませんでした。 (そのパラメータ) – Dani

0

もっと一般的には、任意の間隔、ディメンション、距離の測定値(メトリック)について、あなたが探している構造はボロノイ図です。

関連する問題