Created
June 30, 2011 21:34
-
-
Save bengolder/1057297 to your computer and use it in GitHub Desktop.
Least Cost Path on mesh using NetworkX in Rhino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# import the sys and os libraries for adding modules | |
import sys | |
import os | |
# import the Rhino library | |
import Rhino | |
# manually write out the path to the folder | |
# where networkx is stored, as a list of strings | |
pathbits = [ | |
'C:\\Program Files (x86)', | |
'Python26', | |
'Lib', | |
'site-packages' | |
] | |
# join the list of strings together as a filepath | |
importPath = os.path.join(*pathbits) | |
# add this file path to sys.path so we can import modules | |
# from this folder | |
sys.path.append( importPath ) | |
# import the module that we want | |
import networkx | |
# make a Graph object | |
G = networkx.Graph() | |
# create a set of nodes in the graph, one | |
# for each vertex in the mesh. | |
G.add_nodes_from(range(mesh.Vertices.Count)) | |
# make a function for weighing the connection between | |
# each pair of vertices | |
# as inputs it takes each pair of topology | |
# vertex indices (two integers) | |
def weight_function(i, j): | |
# convert the topology vertex indices (integers) into | |
# the corresponding 3d points | |
p1 = Rhino.Geometry.Point3d((mesh.TopologyVertices[i])) | |
p2 = Rhino.Geometry.Point3d((mesh.TopologyVertices[j])) | |
# use the distance between the points as a base weight | |
base_weight = p1.DistanceTo(p2) | |
# get the change in height | |
deltaZ = p2.Z - p1.Z | |
# the change in height is negative, make it positive (abs value) | |
if deltaZ < 0.0: | |
deltaZ *= -1 | |
# raise the change in height to the power of the flatness bias | |
# and multiply that by the distance | |
return base_weight * (deltaZ ** flatness_bias) | |
# flatness_bias should be an input float generally between 0.0 and 1.0 | |
# build the graph | |
# for each edge | |
for i in range(mesh.TopologyEdges.Count): | |
# get the topology indices of its two vertices | |
pair = mesh.TopologyEdges.GetTopologyVertices(i) | |
# add those indices to the graph to define an edge between nodes | |
G.add_edge(pair.I, pair.J) | |
# use the weight function to assign a weight to that new edge | |
weight = weight_function( pair.I, pair.J ) | |
# assign the weight | |
G[pair.I][pair.J]['weight'] = weight | |
# convert the input vertex indices and convert them to topology indices | |
from_v = mesh.TopologyVertices.TopologyVertexIndex(from_node) | |
to_v = mesh.TopologyVertices.TopologyVertexIndex(to_node) | |
# use network x to find the least cost path between the two nodes | |
topology_list = networkx.algorithms.shortest_paths.generic.shortest_path(G, from_v, to_v, True) | |
# conver the list of topology nodes to 3d points for output | |
a = [Rhino.Geometry.Point3d(mesh.TopologyVertices[v]) for v in topology_list] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment