The depth of a space can serve as a criterion for evaluating the
accessibility of that space.
Consider the image below. It shows two spaces whose layouts are identical.
However, the accessibility of a space changes depending on how the spaces are connected, that is, on the depth.
Same space different evaluation
From the top, space structure · space connection
Consider a slightly more complex spatial structure.
There are two spaces, each consisting of 8 rooms, and the conditions of each space can be visualized as follows (room number 0 is the entrance).
At first glance, there is no difference between the two spaces. However, the difference becomes clear when examining the
graph and the
calculated depth in the picture on the right.
Even when a space (Space 1: 8, Space 2: 7) is in the same location, the depth varies according to the location of the entrance and the connection relationships.
This is evident from the computed depth shown on the far right. The
maximum depths of the two spaces are 6 and 2, respectively.
The conditions of each space
From the top, Space 1 · Space 2
A visibility polygon is a criterion for evaluating the visibility at a specific point.
They can be used to quantitatively evaluate spatial activity or connectivity. The two spaces above are evaluated through the following process.
What is a visibility polygon?
From the left, Obstacles · Visibility polygon
First, a bounding box is created to enclose the entire space, and a square grid is constructed inside the bounding box.
Second, the center point of each grid cell is created, and each point is checked to determine whether it lies inside or outside the space.
Lastly, a visibility polygon is created from each point in the space, and the perimeter of the polygon is measured. The full process is available through the
link.
Applied to Space 2
When the perimeters of the polygons obtained earlier are stored in a list and matched with the grid indices so that larger perimeters are visualized more brightly, the image below is produced.
Space syntax
import math
import random
import Rhino.Geometry as rg
import Rhino.RhinoDoc as rc
import rhinoscriptsyntax as rs
import ghpythonlib.components as gh
import Rhino
class Space:
def __init__(self, curves, resolution):
self.curves = curves
self.resolution = resolution
self.coordinate = self.get_coordinate()
self.grid = self.generate_grid()
def get_coordinate(self):
points = []
for curve in self.curves:
points.extend(rs.CurvePoints(curve))
min_coords = []
max_coords = []
for i in range(2):
min_coord = min([coord[i] for coord in list(set(points))])
max_coord = max([coord[i] for coord in list(set(points))])
min_coords.append(min_coord)
max_coords.append(max_coord)
min_x, min_y = min_coords
max_x, max_y = max_coords
coordinates = [rg.Point3d(min_x, min_y, 0),
rg.Point3d(max_x, min_y, 0),
rg.Point3d(min_x, max_y, 0),
rg.Point3d(max_x, max_y, 0)]
return coordinates
def generate_brep(self):
path = rs.AddLine(rs.AddPoint(0,0,0), rs.AddPoint(0,0,-0.1))
surface = rs.AddPlanarSrf(self.curves)
brep = rs.ExtrudeSurface(surface, path)
return rs.coercebrep(brep)
def generate_boundingbox(self):
plane = rg.Plane.WorldXY
return rg.Rectangle3d(plane, self.coordinate[0], self.coordinate[3])
def generate_grid(self):
bbox_width = self.coordinate[0].DistanceTo(self.coordinate[1])
bbox_height = self.coordinate[0].DistanceTo(self.coordinate[2])
unit_width = bbox_width / self.resolution
unit_height= bbox_height / self.resolution
start_point = self.coordinate[0]
grid = []
for i in range(resolution):
for j in range(resolution):
origin = [start_point[0] + i*unit_width, start_point[1] + j*unit_height, start_point[2]]
unit = rs.AddRectangle(origin, unit_width, unit_height)
grid.append(unit)
return grid
def generate_centroid(self):
grid = self.generate_grid()
centroids = [rs.CurveAreaCentroid(unit)[0] for unit in grid]
return centroids
def generate_ray(self):
centroids = self.generate_centroid()
rays = []
for centroid in centroids:
ray_len = rg.Point3d(100,0,0)
ray = rs.AddLine(centroid, centroid + ray_len)
rays.append(ray)
return rays
def generate_inside_grid(self):
brep = self.generate_brep()
centroids = self.generate_centroid()
inside_check = gh.PointInBrep(brep, centroids, False)
inside_grid = []
inside_centroid = []
for i, check in enumerate(inside_check):
if check == True:
inside_grid.append(self.grid[i])
inside_centroid.append(centroids[i])
return inside_grid, inside_centroid
def generate_grid_surface(self):
inside_grid = [rs.coercecurve(unit) for unit in self.generate_inside_grid()[0]]
return gh.BoundarySurfaces(inside_grid)
def generate_vispolygon(self):
inside_centroid = self.generate_inside_grid()[1]
point_count = 100
radius = 100
vispolygons = []
for centroid in inside_centroid:
isovist = gh.IsoVist(centroid, point_count, radius, self.curves)[0]
vispolygons.append(gh.PolyLine(isovist, True))
return vispolygons
def perimeter_vispolygon(self):
vispolygons = self.generate_vispolygon()
perimeters = []
for vispolygon in vispolygons:
perimeters.append(rs.CurveLength(vispolygon))
return perimeters
if __name__ == "__main__":
space_obj = Space(space, resolution)
all_perimeter = space_obj.perimeter_vispolygon()
min_perimeter = min(space_obj.perimeter_vispolygon())
max_perimeter = max(space_obj.perimeter_vispolygon())
grid_surface = space_obj.generate_grid_surface()