ポイント セットを三角測量し、エッジ上を歩くことは、ポリゴン ベースのウォークが持つ「円形のような」パスの問題を回避するソリューションです。
ポイントが近すぎるランダムなポイント セットは、パスが特定のポイントで交差しているように見える可能性があるため、おそらく必要ありません。このため、ポイント セットを生成するためにポアソン ディスクサンプリング方法のようなものを使用することをお勧めします。このようなポイント セットの三角形分割により、ほぼ同じ長さのセグメント、セグメント間の角度が約 60 のランダム パスが提供されます。 ° そして明らかな交点がない。
アルゴリズム
Delaunay 三角形分割ライブラリを使用すると、アルゴリズムは次のようになります。
初期化するには、
- ポイントセットの生成
- 三角点セット
- 三角形分割 (
lastVisitedVertex
)からランダムな頂点を選択します。
次にループします。
- エッジに接続されている他の頂点がまだアクセスされていない場合にのみ、最後にアクセスした頂点に接続されたランダムなエッジを選択します(このエッジは次のセグメントです)。
- 今来たばかりの頂点を訪問済みとしてマークする
lastVisitedVertex
= 選択したエッジの他の頂点
- もう一度ループするか、パスの長さが目的の長さを超えた場合 (つまり > 25) は終了します。
イラスト
三角形分割されたポアソン ディスク ポイント セット上のランダム パス
[
三角形分割されたランダム ポイント セット上のランダム パス

コード
これは、三角測量にTinourライブラリを使用した Java の例です。三角形分割にライブラリを使用する場合、特定の頂点の接続されたエッジと、特定のエッジを構成する頂点に簡単にアクセスできるライブラリを選択することをお勧めします。
この例では、開始点として (頂点ではなく) ランダムなエッジを選びます。
ArrayList<Vertex> randomPath(List<Vertex> randomPoints, int pathLength) {
IncrementalTin tin = new IncrementalTin(10);
tin.add(randomPoints, null); // insert point set; points are triangulated upon insertion
HashSet<Vertex> visitedVertices = new HashSet<>();
ArrayList<Vertex> pathVertices = new ArrayList<>();
IQuadEdge lastEdge = tin.getStartingEdge(); // get random edge
int n = 0;
while (n <= pathLength) {
List<IQuadEdge> list = new ArrayList<>();
lastEdge.pinwheel().forEach(list::add); // get edges connected to A; add to array
IQuadEdge nextEdge;
int attempts = 0;
do {
nextEdge = list.get(random.nextInt(list.size())); // randomly select connected edge
if (attempts++ > list.size() * 4) {
return pathVertices; // path ended prematurely (no possible edges to take)
}
} while (visitedVertices.contains(nextEdge.getB()) || nextEdge.getB() == null);
lastEdge = nextEdge.getDual(); // A and B flip around, so A is next vertex
pathVertices.add(lastEdge.getB()); // add the point we just came from to path
visitedVertices.add(lastEdge.getB()); // add the point we just came from to visited vertices
n++;
}
return pathVertices;
}