Skip to content

Envelope Selection

This script deletes voxels from the lattice based on a treshold. As inputs it takes 1 or multiple lattices based on which you want to remove the voxels. In this case it removes voxels based on the blockage of sun and of daylight. The output is the resulted output after the deletion of the treshold of both the sun and daylight.

0. Initialization

0.1. Load required libraries

import os
import topogenesis as tg
import pyvista as pv
import numpy as np
import pandas as pd
# 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

0.2. Load Sun Access Lattice

# loading lattice from csv
shaft_path = os.path.relpath('../data/shadow_access_highres.csv')
shad_cast_lattice = lattice_from_csv(shad_cast_path)

# loading lattice from csv
sky_shad_cast_path = os.path.relpath('../data/sky_shadowcasting_highres.csv')
sky_shad_cast_lattice = lattice_from_csv(sky_shad_cast_path)

1. Envelope Selection

1.1. Visualizing the selection

p = pv.Plotter(notebook=True)

base_lattice = shad_cast_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")

def create_mesh(value):

    lattice = np.copy(shad_cast_lattice)
    lattice[shad_cast_lattice > value] *= -0.0
    # Add the data values to the cell data
    grid.cell_arrays["Agents"] = lattice.flatten(order="F")  # Flatten the array!
    # filtering the voxels
    threshed = grid.threshold([0.001, 1.0])
    # adding the voxels
    p.add_mesh(threshed, name='sphere', show_edges=True, opacity=1.0, show_scalar_bar=False, clim=[0.0, 1.0])

    return

p.add_slider_widget(create_mesh, [0, 1], title='Time', value=1.0, event_type="always", style="classic", pointa=(0.1, 0.1), pointb=(0.9, 0.1))
p.show(use_ipyvtk=True)
p = pv.Plotter(notebook=True)

base_lattice = sky_shad_cast_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")

def create_mesh(value):

    lattice = np.copy(shad_cast_lattice)
    lattice[shad_cast_lattice > value] *= -0.0
    # Add the data values to the cell data
    grid.cell_arrays["Agents"] = lattice.flatten(order="F")  # Flatten the array!
    # filtering the voxels
    threshed = grid.threshold([0.001, 1.0])
    # adding the voxels
    p.add_mesh(threshed, name='sphere', show_edges=True, opacity=1.0, show_scalar_bar=False, clim=[0.0, 1.0])

    return

p.add_slider_widget(create_mesh, [0, 1], title='Time', value=1.0, event_type="always", style="classic", pointa=(0.1, 0.1), pointb=(0.9, 0.1))
p.show(use_ipyvtk=True)

1.2. Generating an envelope based on the selection

#setting the threshold
high_threshold = 0.33
low_threshold = 0.0001

#calculating the threshold over the lattices
new_avail_lattice = ((shad_cast_lattice < high_threshold) * (shad_cast_lattice > low_threshold)) * ((sky_shad_cast_lattice < high_threshold) * (sky_shad_cast_lattice > low_threshold))

1.3. Visualize the new available lattice

p = pv.Plotter(notebook=True)

# adding the avilability lattice
new_avail_lattice.fast_vis(p)

p.show(use_ipyvtk=True)

1.4. Save new envelope to CSV

#saving lattices on a desired location csv
csv_path = os.path.relpath('../data/new_shadremove_envelope_lattice.csv')
new_avail_lattice.to_csv(csv_path)
__author__ = "Shervin Azadi"
__editor__ = "Siebren Meines"
__license__ = "MIT"
__version__ = "1.0"
__url__ = "https://github.com/shervinazadi/spatial_computing_workshops"
__summary__ = "Removing voxels based on a treshold"