Floor Plan Movement

Movement through graphs

A critical aspect of architectural design is understanding the way people move through and experience a space. Because such experiences tend to be subjective, they have traditionally been difficult to simulate in the computer. However, by treating the problem more narrowly, we can come up with ways of measuring specific aspects of this experience such as how far people travel between different programs in a space (adjacency), and potential bottlenecks where such movement is concentrated (congestion). These occupant-level metrics give a deeper understanding of the space from the point of view of its occupants, and often relate more to the needs of the client than the global form or structural system of the building. To compute these kinds of metrics we can rely on a branch of mathematics called graph theory, which is based on a data structure called a graph.

A graph is defined by a list of nodes (sometimes called vertices) which store some properties and a list of edges which connect sets of two nodes and represent a relationship between them. In a directed graph, edges represent one-way relationships, while in a bi-directional graph (or bi-graph for short) the connections go both ways.

an undirected graph representation of a floor plan adjacency

Graph structures are very flexible and can represent many types of relationships. If we represent our spatial information as a graph, we can take advantage of many existing algorithms developed for answering specific questions about such structures. For example, if we want to know the length of the shortest path between two points in a space, we can represent all possible paths as a graph of nodes and edges and use Dijkstra’s Algorithm to efficiently compute the shortest path.

Writing the script

This python definition requires the standard Grasshopper components Construct Mesh, Closest Points, Line, Jitter, and Split List. In addition, the Remove Duplicate Lines component from the Karamba library is used to make sure that only valid, non-duplicated lines are passed into the Python script.

inputs and outputs of python script node

import Rhino.Geometry as rh

import sys
sys.path.append('\\'.join(lib_path.split('\\')[:-1]))
import gd_tools_2 as gd

line_data = []

for line in lines:
    p_1 = line.ToNurbsCurve().PointAtStart
    p_2 = line.ToNurbsCurve().PointAtEnd
    line_data.append([[p_1.X, p_1.Y, p_1.Z], [p_2.X, p_2.Y, p_2.Z]])

graph = gd.lines2graph(line_data)

print graph

origins = [[p.X, p.Y, p.Z] for p in origins]
destinations = [[p.X, p.Y, p.Z] for p in destinations]

paths = []

for i in range(len(origins)):

    origin_node = graph.search_node(origins[i])
    dest_node = graph.search_node(destinations[i])
    
    path_nodes = graph.get_route(origin_node, dest_node)
    
    if path_nodes:
        print "[", str(i), "] route found -->", [n.get_id() for n in path_nodes]
    else:
        print "[", i, "] no route found"
        continue
    
    all_points = [rh.Point3d(*n.get_coords()) for n in path_nodes]
    paths.append( rh.PolylineCurve(all_points) )

print graph

edges = [rh.Line(rh.Point3d(*e.get_nodes()[0].get_coords()), rh.Point3d(*e.get_nodes()[1].get_coords())) for e in graph.get_edges()]
edge_traversals = [e.get_traversal() for e in graph.get_edges()]

nodes = [rh.Point3d(*n.get_coords()) for n in graph.get_nodes()]
node_traversals = [n.get_traversal() for n in graph.get_nodes()]

Defining the inputs

Geometry in Grasshopper will be fed to the inputs into the Python script. The code will create a graph from a set of line segments and then route paths between each pair of origin and destination points. For this to work the lines should connect at their end points.

To generate the lines, we need to create some starting and destination points and then connect each one to a set of its closest neighbors. Starting points S will in this case be entry points from stariwells and from every working desk. Destination points D will be to every meeting room and amenity.

starting points (S) and destination points (D)

The origin and destination points will now be looped over to generate paths, which we will use a list comprehension to iterate over each edge in the graph and store it’s traversals in a list. These geometries and traversal counts will be output from the Python script back to Grasshopper where we can use them for visualization and computing metrics.

Djirkstra algorithm finding shortest path
Final simulation
Year

2019

Tools

Grasshopper

Language

Python