Skip to content

Floor closeness

0. Initialization

import os
import topogenesis as tg
import pyvista as pv
import trimesh as tm
import numpy as np
import networkx as nx
from scipy.interpolate import RegularGridInterpolator
import copy

1.1. Loading in the lattice

lattice_path = os.path.relpath("../data/solar_envelope_324.csv")

solar_envelope = tg.lattice_from_csv(lattice_path)
full_lattice = solar_envelope * 0 + 1

2.1 Creating a vertical adjacency matrix

# get the amount of voxels in the z direction
vox_count = len(solar_envelope[0][0])

# initialize an adjacency matrix
adj_mtrx = np.zeros((vox_count,vox_count))

# set the connecting values of the adjacency matrix to 1
for i in range(vox_count):
    if i == 0:
        adj_mtrx[i, i + 1] = 1
        continue
    if i == vox_count - 1:
        adj_mtrx[i, i - 1] = 1
        continue
    else:
        adj_mtrx[i, i + 1] = 1
        adj_mtrx[i, i - 1] = 1

2.2 Turning it into a networkx datastructure and calculating distances

g = nx.from_numpy_array(adj_mtrx)
dist_mtrx_vertical = nx.floyd_warshall_numpy(g)

2.3 Selecting floor level and mapping vertical distances between 0 and 1

floor_dist = dist_mtrx_vertical[2] # specified floor level

max_valid = np.ma.masked_invalid(floor_dist).max() # find max distance

floor_dist_mapped = 1 - (floor_dist / max_valid) # map values between 0 and 1 with max distance

2.4 Mapping the values to the full lattice

floor_dist_mapped_full = []
height = len(floor_dist_mapped)

# mapping the colomn of values to the full lattice
for i in range(len(full_lattice)*len(full_lattice[0])*len(full_lattice[0][0])):
    floor_dist_mapped_full.append(floor_dist_mapped[i % height])

# turning it into an np array
floor_dist_mapped_full = np.array(floor_dist_mapped_full)

# reshaping the array
floor_dist_lattice_full = floor_dist_mapped_full.reshape(full_lattice.shape)

# forming the lattice to the solar envelope
floor_dist_lattice = floor_dist_lattice_full * solar_envelope 

3.1 Visualizing the floor level lattice

pv.set_plot_theme("document")

# convert mesh to pv_mesh
def tri_to_pv(tri_mesh):
    faces = np.pad(tri_mesh.faces, ((0, 0),(1,0)), 'constant', constant_values=3)
    pv_mesh = pv.PolyData(tri_mesh.vertices, faces)
    return pv_mesh

base_lattice = floor_dist_lattice
# initiating the plotter
p = pv.Plotter(notebook=True)

# Create the spatial reference
grid = pv.UniformGrid()

# Set the grid dimensions: shape because we want to inject our values
grid.dimensions = base_lattice.shape
# The bottom left corner of the data set
grid.origin = base_lattice.minbound
# These are the cell sizes along each axis
grid.spacing = base_lattice.unit

# Add the data values to the cell data
grid.point_arrays["Floor closeness"] = base_lattice.flatten(order="F")  # Flatten the Lattice

# adding the volume
opacity = np.array([0,0.6,0.6,0.6,0.6,0.6,0.6])
p.add_volume(grid, cmap="coolwarm", clim=[0, 1.0],opacity=opacity, shade=False)

# adding the meshes
context_path = os.path.relpath("../data/immediate_context.obj")
context_mesh = tm.load(context_path)
p.add_mesh(tri_to_pv(context_mesh), opacity=0.1, style='wireframe')

# plotting
cpos = [(785.8704805788776, 708.4540755788776, 741.8613927288776),
 (65.08283250000001, -12.333572500000002, 21.07374465),
 (0.0, 0.0, 1.0)]
p.camera_position = cpos
p.window_size = 2000, 2000
p.show(use_ipyvtk=True)
# p.screenshot("floor_2")
print(p.camera_position)

3.2 Exporting the lattice

csv_path = os.path.relpath('../data/closeness_ground_floor_324.csv')
floor_dist_lattice.to_csv(csv_path)