Shafts
In this notebook, the shafts that connect the groundfloors, entrances and all floors above are being generated in a lattice.
0. Initialization
0.1. Load required libraries
import os
import topogenesis as tg
import pyvista as pv
import trimesh as tm
import numpy as np
import networkx as nx
import pandas as pd
from sklearn.cluster import KMeans
np.random.seed(0)
import copy
# extra import function
def lattice_from_csv(file_path):
# read metadata
meta_df = pd.read_csv(file_path, nrows=3)
shape = np.array(meta_df['shape'])
unit = np.array(meta_df['unit'])
minbound = np.array(meta_df['minbound'])
# read lattice
lattice_df = pd.read_csv(file_path, skiprows=5)
# create the buffer
buffer = np.array(lattice_df['value']).reshape(shape)
# create the lattice
l = tg.to_lattice(buffer, minbound=minbound, unit=unit)
return l
shaft_stencil = tg.create_stencil("von_neumann", 1, 2)
shaft_stencil.set_index([0, 0, 0], 0)
shaft_stencil.set_index([1, 0, 0], 0)
shaft_stencil.set_index([-1, 0, 0], 0)
shaft_stencil.set_index([0, 1, 1], 1)
shaft_stencil.set_index([0, 2, 1], 1)
shaft_stencil.set_index([0, 2, 2], 1)
shaft_stencil.set_index([0, 1, 2], 1)
shaft_stencil.set_index([0, 2, 0], 1)
shaft_stencil.set_index([0, 0, 2], 1)
shaft_stencil.set_index([0, 1, 1], 1)
shaft_stencil.set_index([0, -1, 1], 1)
shaft_stencil.set_index([0, -1, 2], 1)
shaft_stencil.set_index([0, -1, -1], 1)
shaft_stencil.set_index([0, 1, -1], 1)
shaft_stencil.set_index([0, 2, -1], 1)
0.3. Load the envelope lattice as the avialibility lattice
# loading the lattice from csv
lattice_path = os.path.relpath('../data/highres_envelope.csv')
avail_lattice = lattice_from_csv(lattice_path)
init_avail_lattice = tg.to_lattice(np.copy(avail_lattice), avail_lattice)
0.4. Load Agents Information
# loading program (agents information) from CSV
prgm_path = os.path.relpath('../data/program_exported.csv')
agn_info = pd.read_csv('../data/program_exported.csv',delimiter=";")
agn_ids = agn_info["space_id"].values
agn_prefs = agn_info
a_pref = agn_prefs.loc[0]
agn_num = len(agn_info)
1.1 determine all shaft locations at the location of the entrance voxel
start_shaft_lattice = avail_lattice * 0 - 1
start_shaft_lattice[(83, 7, 1)] = 3
start_shaft_lattice[(40, 20, 1)] = 3
start_shaft_lattice[(70, 1, 1)] = 3
start_shaft_lattice[(83, 20, 1)] = 3
occupation_latice = (start_shaft_lattice > -1).astype(int)
# compute the sum over the columns
column_sum = np.sum(occupation_latice, axis = 2)
max_value = np.max(column_sum)
filled_col_list = []
for i in range(1, max_value + 1):
# find adresses of columns
column_adress = np.where(column_sum == i )
filled_collumns = np.array(column_adress).T
filled_col_list.append(filled_collumns)
fill_col_stacked = np.vstack(filled_col_list)
clusters = len(fill_col_stacked)
kmeans = KMeans(n_clusters=clusters, random_state=0).fit(fill_col_stacked)
col_labels = kmeans.labels_
cluster_centers = kmeans.cluster_centers_
# creating an empty occ lattice
cluster_lattice = avail_lattice * 0 - 1
# iterating over each filled column
for col, lab in zip(fill_col_stacked, col_labels):
cluster_lattice[col[0], col[1], :] = lab
1.2. generate height of each shaft
rounded_cluster_centres = np.rint(cluster_centers).astype(int)
shaft_placement_lattice = avail_lattice * 0
# iterating over each shaft
for i, cen in enumerate(rounded_cluster_centres):
shaft_placement_lattice[cen[0], cen[1], :] = 1
trimmed_shaft_lattice = shaft_placement_lattice * init_avail_lattice
p = pv.Plotter(notebook=True)
base_lattice = trimmed_shaft_lattice
# Set the grid dimensions: shape + 1 because we want to inject our values on the CELL data
grid = pv.UniformGrid()
grid.dimensions = np.array(base_lattice.shape) + 1
# The bottom left corner of the data set
grid.origin = base_lattice.minbound - base_lattice.unit * 0.5
# These are the cell sizes along each axis
grid.spacing = base_lattice.unit
# adding the boundingbox wireframe
p.add_mesh(grid.outline(), color="grey", label="Domain")
# adding the avilability lattice
# init_avail_lattice.fast_vis(p)
# adding axes
p.add_axes()
p.show_bounds(grid="back", location="back", color="#aaaaaa")
# Add the data values to the cell data
grid.cell_arrays["Agents"] = base_lattice.flatten(order="F").astype(int) # Flatten the array!
# filtering the voxels
threshed = grid.threshold([0.9, agn_num - 0.9])
# adding the voxels
p.add_mesh(threshed, name='sphere', show_edges=True, opacity=1.0, show_scalar_bar=False)
# p.add_slider_widget(create_mesh, [0, n_frames], title='Time', value=0, event_type="always", style="classic", pointa=(0.1, 0.1), pointb=(0.9, 0.1))
p.show(use_ipyvtk=True)
#saving and plotting
png_path = os.path.relpath('../screenshots/6.3_shafts.png')
p.show(screenshot= png_path)
2.3. Saving lattice frames in CSV
# save the ground floor latice to csv
csv_path = os.path.relpath('../data/shaft_lattice.csv')
trimmed_shaft_lattice.to_csv(csv_path)
import pickle
lattice_pickle_path = os.path.relpath('../data/shaft_lattice.p')
pickle.dump(trimmed_shaft_lattice, open(lattice_pickle_path,"wb"))
Credits
__author__ = "Shervin Azadi and Pirouz Nourian"
_Chief_editor_ = "Maartje Damen"
_Co_editor_ = "Eda Akaltun"
_Co_editor_ = "Siebren Meines"
_editor_mentor_ = "Shervin Azadi"
__license__ = "MIT"
__version__ = "1.0"
__url__ = "https://github.com/shervinazadi/spatial_computing_workshops"
__summary__ = "Spatial Computing Design Studio Workshop on MCDA and Path Finding for Generative Spatial Relations"