Input0にConvertline SOPでポリライン化した地形を、Input1に始点と終点を含むポリラインを差す。
// RunOver: Detail
// input0: Polyline Graph
// input1: Polyline
vector start = point(1, "P", 0);
vector goal = point(1, "P", 1);
// 始点
vector cross;
vector uv;
vector origin = start + set(0, 1, 0) * 50000;
vector dir = set(0, -1, 0) * 100000;
int hitId = intersect(1, origin, dir, cross, uv);
if(hitId >= 0)
i@startId = nearpoint(0, cross);
else
i@startId = nearpoint(0, start);
// 終点
origin = goal + set(0, 1, 0) * 50000;
dir = set(0, -1, 0) * 100000;
hitId = intersect(1, origin, dir, cross, uv);
if(hitId >= 0)
i@goalId = nearpoint(0, cross);
else
i@goalId = nearpoint(0, goal);
ポイントから隣接するエッジからの情報を格納する。
// RunOver: Points
// 隣り合うポイント
int neighbours[] = neighbours(0, @ptnum);
i[]@connectedPoint = neighbours;
// 隣り合うポリライン
int connectedPrim[] = pointprims(0, @ptnum);
i[]@connectedPrim = connectedPrim;
// ポリラインの長さ
f[]@distance;
for(int i = 0; i < len(neighbours); i++)
{
vector pos = point(0, "P", neighbours[i]);
f[]@distance[i] = length(pos - @P);
}
Python SOPでダイクストラ法の経路探索を記述する。
#
# ダイクストラの経路探索
#
node = hou.pwd()
geo = node.geometry()
from collections import deque
import time
# Start
start_time = time.time()
# 地点クラス
class Node:
def __init__(self, connect, dist):
# 直前のインデックス
self.prevPt = -1
# フラグ
self.flag = 0
# コスト(一応大きな数を入れておく)
self.totalCost = 100000.0
# 接続する道路
self.connect = connect
# 道路の距離
self.dist = dist
start = geo.intAttribValue('startId')
goal = geo.intAttribValue('goalId')
# ルートリスト
routeList = deque([])
# ポイント総数
nPoints = len(geo.points())
# 分岐するルートと距離の情報を格納する
connect = []
dist = []
for pt in geo.points():
connect.append(pt.intListAttribValue("connectedPoint"))
dist.append(pt.floatListAttribValue("distance"))
# ノードクラスのリストを初期化
node = []
for i in range(nPoints):
node.append(Node(connect[i], dist[i]))
#
# 計算開始
#
# startからのルートをリストに入れる
node[start].flag = 1
node[start].prevPt = start
node[start].totalCost = 0.0
routeList.append(start)
# 処理
count = 0
while len(routeList) > 0:
# リストから引き出す
currentPt = routeList.popleft()
for i in range(len(node[currentPt].connect)):
nextPt = node[currentPt].connect[i]
cost = node[currentPt].totalCost + node[currentPt].dist[i]
# すでに探索済みのポイント
if node[nextPt].flag == 1:
if cost < node[nextPt].totalCost:
node[nextPt].totalCost = cost
node[nextPt].prevPt = currentPt
routeList.append(nextPt)
# 新規に探索するポイント
else:
node[nextPt].totalCost = cost
node[nextPt].prevPt = currentPt
# 探索済みフラグを立てる
node[nextPt].flag = 1
# ゴールの地点なら次の地点は探索しない
if nextPt != goal:
routeList.append(nextPt)
count = count + 1
# ルートを検索
if node[goal].prevPt != -1:
route = []
pt = goal
while(pt != start):
route.append(pt)
pt = node[pt].prevPt
route.append(start)
route.reverse()
# Detailに保存
geo.addArrayAttrib(hou.attribType.Global, 'route', hou.attribData.Int, 1)
geo.setGlobalAttribValue('route', route)
geo.addAttrib(hou.attribType.Global, 'dist', 0.0)
geo.setGlobalAttribValue('dist', node[goal].totalCost)
geo.addAttrib(hou.attribType.Global, 'start', 0)
geo.setGlobalAttribValue('start', start)
geo.addAttrib(hou.attribType.Global, 'goal', 0)
geo.setGlobalAttribValue('goal', goal)
#print route
print (node[goal].totalCost)
print ("num search:" + str(count))
# End
elapsed_time = time.time() - start_time
print ("dykstra_route::time:{0}".format(elapsed_time) + "[sec]")
Python SOPの結果からラインを生成するVEXコード。
// RunOver: Detail
// input0: None
// input1: Python SOP
int route[] = detail(1, "route", 0);
int prim = addprim(0, "polyline");
for(int i = 0; i < len(route); i++)
{
vector pos = point(1, "P", route[i]);
int pt = addpoint(0, pos);
addvertex(0, prim, pt);
}
環境:Houdini 19.5.752