多くのエンティティにとって効率的な2D Java見通し線?


7

今日の私の問題はこれです:

地図に写っているたくさんの人の画像

私は多くの民間人を囲んでいますが、それらはarraylistに保存されているクラスです。

彼らが別の民間人のパニックを見たとき、彼らはパニックになり始めて、それは広がるでしょう。

まずStep()、イテレーターをループして各クラス関数を呼び出します。次に、Step()関数では、別の民間のイテレータを通過します。通過するときに、イテレータで他の民間人を見ることができるかどうかを検出しようとします。これは、パフォーマンス時間が0から50ミリ秒になり、市民が100人いる場合です。

これは私が修正する必要のある問題です。オブジェクトがポイントaからポイントbの邪魔になっているかどうかを簡単に検出できるようにしようとしました。

見通し線のコードは次のとおりです。

public static Object LOS(int x, int y, int x2, int y2, String Scan, Object Me, Object You) {
   DirectionX = (x-x2)/Quality;
   DirectionY = (y-y2)/Quality;
   CurrentX = x;
   CurrentY = y;
   String[] ScanArray = Scan.split(":");
   for(int I=0;I<=Quality;I++) {
      for(String Type: ScanArray) {
         if(Type.equals("Boxs")) {
            Iterator it=Level.Boxs.iterator();
            while(it.hasNext()) {
               Box Box = (Box)it.next();
               if(Me!=Box&&You!=Box) {
                  //Collision = Tools.Collision((int)(CurrentX-(Width/2)), (int)(CurrentY-(Width/2)), Width, Width, Box.GetX(), Box.GetY(), Box.GetWidth(), Box.GetHeight(), 1);
                  boolean Col = Tools.BasicCollision((int)(CurrentX-(Width/2)), (int)(CurrentY-(Width/2)), Width, Width, Box.GetX(), Box.GetY(), Box.GetWidth(), Box.GetHeight());
               }
            }
         }
      }

      CurrentX-=DirectionX;
      CurrentY-=DirectionY;
   }
   return null;
}

頭痛の種がある場合、基本は次のとおりです。

次のように使用して、その間の10ポイントを計算し、それが内部にあるかどうかを検出しBasicCollisionます。

public static boolean BasicCollision(int x, int y, int width, int height, int x2, int y2, int width2, int height2) {
   if(x<x2+width&&x+width>x2&&y<y2+height&&y+height>y2) {
      return true;
   } else {
      return false;
   }
}

私の質問は次のとおりです。大量のパフォーマンスに深刻な影響を与えないこの見通し線を検出する簡単な方法はありますか?フィードバックはありますか?


2
1. 404をオンにしますLOS.txt2.すべてのコードを表示する必要はありません。SSCCEを提供します
マットボール

Mattの編集ヘルプをありがとう、404を修正しました:)重要なコードのみを示しました。

回答:


5

1つの考えは、パニックでない人々とパニックな人々を別々のリストNとPに維持し、LOSチェックを<n、p>∈N×Pに制限することです。そうすることで、同じ状態の人々をチェックすることはなく、スピードが向上します。アップ。

別のこと(既に行っている可能性があります-確かではありません)は、非パニックがパニックになったと判断したら、以前の非パニックの残りのチェックをすぐに停止することです。これは、固定マップの人口サイズの増加に伴うアルゴリズムのスケーリングに役立ちます。母集団が非常に大きくなった場合は、100%パニックにすばやく収束する必要があります。つまり、以下のコメントに記載されているように、これ以上のチェックは必要ありません。


良いアドバイス、私はちょうどそのフィルターを追加しました、パニックが0%の場合は1ミリ秒、100%の場合は50になりますが、これは間違いなく実用的です。

何かが正しく聞こえません-チェックの数は(tp)* pである必要があります。ここで、t =合計、p =パニックです。したがって、p = tの場合、チェックの数は0になります。直感的には、誰もがパニックになったら、それ以上チェックを行う理由はありません。リストNには、母集団全体が含まれているのではなく、パニックが含まれていますか?私は100%ですべてのパニックを人口全体と比較していると思います、それはそれが遅い理由です。

2

あなたの記述から、あなたのコードは2人の民間人の可能なすべてのペアを反復しているようです。図面はこれが不要であることを示唆しています。ある種の幾何学的インデックスを使用して、近くの民間人を追跡できます。次に、最初にそれらをテストします。LOSにある場合は、パニックになります。それ以外の場合は、さらに遠くの民間人をテストします。


ありがとう、私はすでにそれをしました、最適化の前にそれは100ミリ秒でした。

0

いくつかのオプションがあります。

A)人々が他の人の叫び声を聞いてパニックになる可能性があると仮定します。したがって、視線コードはそれほど重要なXDではありません。

B)Aを選択できない場合は、一般市民ごとにこれを行う必要があります。

  1. 2人の民間人の間のセグメントの長さが一定の値以下かどうかを計算します。
  2. このセグメントが多角形(あなたの場合は長方形)と交差するかどうかを計算します。

2が最も高価な計算であることを考えると、2の前に1を実行する必要があります。これにより、作業量が大幅に削減されます。また、すでに行った計算について、ある種の「メモリ」を考慮する必要があります。例:C1-C2セグメントを処理したばかりの場合は、C2-C1を再度実行しないでください。

それに加えて、2を最適化する必要があります。セグメントが長方形と交差するかどうかをテストすることは、特定のセグメントが4つのセグメントと交差するかどうかをテストすることと同じです。あなたがそれらの1つと交差したとき、私たちは民間人がお互いを見ないことを確信しているので、長方形の残りのセグメントを処理することは意味がありません。

これは、ラインセグメントの交差問題と呼ばれる典型的な幾何学的問題であるため、インターネット上で多くのオープンソースコードを見つけることができます。ほとんどの人は、いくつかのデータ構造とともにスイープラインアルゴリズムを使用します。


広範な洞察をありがとう、私はこれらのアルゴリズムのいくつかのwiki研究を現在行っています。
user940982 2011

0

ポータルで結合されたゾーンとして部屋を扱う場合は、各部屋と隣接する部屋の所定のポータルから見える部分の可視性スキャンのみを実行する必要があります。

あなたの視線は、民間人が直面している方向を考慮していない可能性がありますか?このような場合、柱などの障害物が含まれている部屋や、角を曲がる部屋を別々の凸型ゾーンに分割し、同じゾーン内のすべての民間人がすべて互いに見えるようにするとします。他のすべての可視性チェックを回避するために、重複する凹型ゾーンを使用し、民間人が他の民間人と同じゾーンにできるだけ多くを見つけることができるように、一度に複数のゾーンに入ることができるようにすることで、それをさらに進めることができます。

地形が不均一でエージェント数が多い場合は、このO(n)スイープに興味があるかもしれません(Nは地形を分割したグリッドの粒度です):ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.