2016-10-05 8 views
1

現在、私は線に沿って見えて見えない点を教えてくれる見通し線アルゴリズムを実装しています。だから、私が丘陵地帯の頂上に立っていると、私はどこに見えるか見えないかを知ることができます。3D Line-of-Sightアルゴリズム

点Aから点Bまでに生成される線には、AとBの間に均等に配置された点の数が含まれています。Aから始まり、仰角がAとBの間にあることがわかります。alphaAngle

次に、AとBの間の各点について、私はAとその点の間の仰角を得る。その点がこれまでの最高仰角(alphaAngleを除く)であれば、その点としてマークします。さもなければ、それは仰角が低く、そのため私はそれを見ることができず、その点をhasLOS = falseとマークするべきです。ここで

は、私が使用するいくつかのオブジェクト定義は、以下のとおりです。ここで

struct TerrainProfilPnt 
{ 
double m_x_lon; //lon 
double m_y_lat; //lat 
double m_z_elev; //elev 
bool m_hasLOS; //Does this point have line of sight from another point? 
}; 

class TerrainProfilePartitioner; // Holds a collection of points that make up the line 

は私のアルゴリズムが書き出されている、しかし、それは正しい結果を返しません。どちらかといえば、逃げてはいけないときに喪失していると主張しています(ある丘の後ろから別の丘の反対側に向かうように、私はそれを見ることができません)。 それは私が(山の下の谷の上の丘の上)すべき終点を見ることができないと主張する。だから、私は視線を見つけるのが間違っているのか、それともコードで間違って実装しているのか疑問に思います。

using Point = TerrainProfilePnt; 

    auto pointsInLine = terrainProfilePartitioner->GetPoints(); 
    auto& pointsVec = pointsInLine->GetVector(); 
    std::vector<Point> terrainProfileVec; 
    terrainProfileVec.reserve(pointsVec.size()); 

    double start_xlon = 0.0f; 
    double start_ylat = 0.0f; 
    double start_zelev = 0.0f; 

    double end_xlon = 0.0f; 
    double end_ylat = 0.0f; 
    double end_zelev = 0.0f; 

    //The angle between the starting point and the ending point 
    double initialElevAngle = 0.0f; 


    //Assemble the first and last points 
    start_xlon = pointsVec.front().x(); 
    start_ylat = pointsVec.front().y(); 
    GetPointElevation(start_xlon, start_ylat, start_zelev);  
    end_xlon = pointsVec.back().x(); 
    end_ylat = pointsVec.back().y(); 
    GetPointElevation(end_xlon, end_ylat, end_zelev); 

    //Calculate the angle between the beginning and ending points 
    initialElevAngle = atan2(start_zelev, end_zelev) * 180/M_PI; 

    Point initialPoint; 
    initialPoint.m_x_lon = start_xlon; 
    initialPoint.m_y_lat = start_ylat; 
    initialPoint.m_z_elev = start_zelev; 
    initialPoint.m_hasLOS = true; 

    //pointsVec.push_back(initialPoint); 
    terrainProfileVec.push_back(initialPoint); 

    double oldAngle = 0.0f;; 
    bool hasOldAngle = false; 
    for (std::size_t i = 1; i < pointsVec.size(); ++i) 
    { 
     Point p; 
     p.m_x_lon = pointsVec.at(i).x(); 
     p.m_y_lat = pointsVec.at(i).y(); 
     GetPointElevation(p.m_x_lon, p.m_y_lat, p.m_z_elev); 

     double newAngle = atan2(start_zelev, p.m_z_elev) * 180/M_PI; 
     if (!hasOldAngle) 
     { 
      hasOldAngle = true; 
      oldAngle = newAngle; 
      p.m_hasLOS = true; 
     } 
     else 
     { 
      if (newAngle < oldAngle) 
      { 
       p.m_hasLOS = false; 
      } 
      else 
      { 
       oldAngle = newAngle; 
       p.m_hasLOS = true; 
      } 
     } 

    } 

    auto terrainPrfileSeq = new Common::ObjectRandomAccessSequence<TerrainProfilePnt>(terrainProfileVec); 

    return terrainPrfile 

答えて

2

atan2(start_zelev, p.m_z_elev)は無意味です。あなたはdistancepinitialPoint間の水平距離である

atan2(distance, p.m_z_elev - start_zelev); 

を必要としています。

1

私はいくつかの問題を参照してください:あなたはA昇順からの距離によってポイントをソートするだけ高度を使用していません。おそらく遅いかもしれない各地図位置のためのゴニオメトリックスを使用する。私の代わりに別のアプローチを使用します。

  1. マップ全体のために
  2. LOS=falseを設定するには、(B-A)があなたの視線方向とtある

    P(t)=A+(B-A).t 
    

    がずつ増加するパラメータであるDDA線補間を書きますあなたのグリッドサイズより少し小さい(何も見逃さないように)。これは遅いゴニオメトリックなしでlong,latを与えるでしょう。

    次に、マップ上のオブジェクトを見つけます。それはトポロジがソートされている場合、これは視認性O(1)又はO(log(n).log(m))

  3. 試験各実際の位置P(t)

    のいずれかです。 trueLOS=trueに設定され、ループ#2の場合は、すべてを停止します。

ところでこれは時々ray-castingと呼ばれています。

関連する問題