gist_demo / utils /isoutil.py
Mikhael Johanes
clean up
0526506
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
def pol2car(rho, pi, xi, yi):
x = rho * np.cos(pi) + xi
y = rho * np.sin(pi) + yi
return (x, y)
def plot_isovist(isovists, show_axis=False, s=0.1, figsize=(5,5)):
#transpose the matrix
# isovists = np.transpose(isovists, (isovists.ndim-1, isovists.ndim-2))
plt.switch_backend('agg')
fig = plt.figure(figsize=figsize)
points = []
res = np.pi/90
isovist = isovists
for j, rho in enumerate(isovist):
if rho < 1.0:
pt = pol2car(rho, j*res, 0, 0)
points.append(pt)
x = [i[0] for i in points]
y = [i[1] for i in points]
ax = fig.add_subplot(111)
ax.set_aspect('equal')
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
if not show_axis:
ax.axis('off')
ax.scatter(x, y, s, 'black')
return fig
def isovist_to_cartesian_a(isovist, x, y, scale):
points = []
xy = (x, y)
res = np.pi/len(isovist)*2
isovist = isovist * scale
for j, rho in enumerate(isovist):
pt = pol2car(rho, j*res, xy[0], xy[1])
points.append(pt)
points = np.stack(points)
return(points)
def isovist_to_cartesian_segment_a(isovist, x, y, scale, max=0.98, min = 0.1, d=0.1):
points = []
segment = []
xy = (x, y)
res = np.pi/len(isovist)*2
isovist = isovist * scale
p_rho = isovist[-1]
for j, rho in enumerate(isovist):
delta = abs(p_rho-rho)
if j == 0:
first_rho = rho
if rho < max * scale and rho > min * scale and delta < d * scale:
pt = pol2car(rho, j*res, xy[0], xy[1])
segment.append(pt)
else:
points.append(segment)
segment = []
p_rho = rho
if first_rho < max * scale and first_rho > min * scale and abs(rho-first_rho)< d * scale :
if len(points) > 0:
segment.extend(points[0])
points[0]=segment
else:
points.append(segment)
else:
points.append(segment)
segments = []
for i in range(len(points)):
if len(points[i])>0:
segment = np.stack(points[i])
segments.append(segment)
return(segments)
def index_to_loc_grid(idx, d):
if idx == 0:
return np.array((0., 0.), dtype=np.float32)
elif idx == 1:
return np.array((d, 0.), dtype=np.float32)
elif idx == 2:
return np.array((d, d), dtype=np.float32)
elif idx == 3:
return np.array((0., d), dtype=np.float32)
elif idx == 4:
return np.array((-d, d), dtype=np.float32)
elif idx == 5:
return np.array((-d, 0.), dtype=np.float32)
elif idx == 6:
return np.array((-d, -d), dtype=np.float32)
elif idx == 7:
return np.array((0., -d), dtype=np.float32)
elif idx == 8:
return np.array((d, -d), dtype=np.float32)
else:
raise NameError('Direction unknown')
# showing isovist sequence grid
def seq_show_grid(locs, isovists, d=0.2, figsize=(8, 8), center=False, lim=1.5, alpha=0.02, rad=0.9, b_width=1.0, calculate_lim=False):
# walk trough the sequence
p_loc = np.array((0, 0))
b_segments = []
b_points = []
isovists_pts = []
res = np.pi/128
cartesian_locs = []
for loc, isovist in zip(locs, isovists):
rel_pos = index_to_loc_grid(loc, d) + p_loc
for j, rho in enumerate(isovist):
if rho < rad :
pt = pol2car(rho, j*res, rel_pos[0], rel_pos[1])
b_points.append(pt)
segments = isovist_to_cartesian_segment_a(isovist, rel_pos[0], rel_pos[1], 1.0)
b_segments.extend(segments)
isovists_pts.append(isovist_to_cartesian_a(isovist, rel_pos[0], rel_pos[1], 1.0))
cartesian_locs.append(rel_pos)
p_loc = rel_pos
if len(b_points) > 0:
b_points = np.stack(b_points)
else:
b_points =[]
isovists_pts = np.stack(isovists_pts)
# b_segments = np.stack(b_segments)
cartesian_locs = np.stack(cartesian_locs)
# set graphic properties
isovist_path_width = 0.1
isovist_path_pt1 = 6.0
isovist_path_pt2 = 10.0
isovist_boundary_pt = 0.05
if center == True:
bbox = get_bbox(b_points)
center_pt = get_center_pts(bbox, np_array=True)
b_points = [ pt - center_pt for pt in b_points]
isovists_pts = [ pt - center_pt for pt in isovists_pts]
b_segments = [ pt - center_pt for pt in b_segments]
cartesian_locs = [ pt - center_pt for pt in cartesian_locs]
# resize image
if calculate_lim == True:
if bbox is not None:
max = np.max(np.abs(bbox))
else:
max = 2.0
if max > 2.0:
lim = ((max // 0.5) + 1) * 0.5
isovist_path_width *= 2.0/lim
isovist_path_pt1 *= 2.0/lim
isovist_path_pt2 *= 2.0/lim
isovist_boundary_pt *= 2.0/lim
fig, ax = plt.subplots(1,1, figsize=figsize, dpi=96)
# isovists
isovist_poly = []
for isovist_pts in isovists_pts:
isovist_poly.append(Polygon(isovist_pts, True))
r = PatchCollection(isovist_poly)
r.set_facecolor('#00aabb')
r.set_edgecolor(None)
r.set_alpha(alpha)
ax.add_collection(r)
# isovist path
q = PatchCollection([Polygon(cartesian_locs, False)])
q.set_facecolor('none')
q.set_edgecolor('red')
q.set_linewidth(isovist_path_width)
# q.set_linestyle('dashed')
ax.add_collection(q)
# start_pt
ax.scatter([x[0] for x in cartesian_locs[:1]], [x[1] for x in cartesian_locs[:1]], s = isovist_path_pt1, c='k', marker='s')
# sequence
ax.scatter([x[0] for x in cartesian_locs[1:-1]], [x[1] for x in cartesian_locs[1:-1]], s = isovist_path_pt1, c='red')
# end pt
ax.scatter([x[0] for x in cartesian_locs[-1:]], [x[1] for x in cartesian_locs[-1:]], s = isovist_path_pt2, c='k', marker='x')
# boundaries
edge_patches = []
for segment in b_segments:
if len(segment) > 5:
polygon = Polygon(segment, False)
edge_patches.append(polygon)
p = PatchCollection(edge_patches)
p.set_facecolor('none')
p.set_edgecolor('#000000')
p.set_linewidth(b_width)
ax.scatter([x[0] for x in b_points], [x[1] for x in b_points], s = isovist_boundary_pt, c='#000000',)
# ax.add_collection(p)
# style
ax.set_aspect('equal')
lim = lim
ax.set_xlim(-lim,lim)
ax.set_ylim(-lim,lim)
ax.set_xticks([])
ax.set_yticks([])
ax.axis('off')
return fig
# plotting isovist sequence grid
def plot_isovist_sequence_grid(locs, isovists, figsize=(8,8), center=False, lim=1.5, alpha=0.02, rad=0.9, b_width=1.0, calculate_lim=False):
fig = seq_show_grid(locs, isovists, figsize=figsize, center=center, lim=lim, alpha=alpha, rad=rad, b_width=b_width, calculate_lim=calculate_lim)
# for plot with torchvision util
fig.canvas.draw()
data = np.frombuffer(fig.canvas.tostring_rgb(), dtype=np.uint8)
w, h = fig.canvas.get_width_height()
im = data.reshape((int(h), int(w), -1))
im = im.transpose((2, 0, 1))
plt.close()
return im
def get_bbox(pts):
if len(pts) > 0:
if type(pts) is list:
pts = np.stack(pts)
bbox = np.min(pts[:, 0]), np.max(pts[:, 0]), np.min(pts[:, 1]), np.max(pts[:, 1])
return bbox
else:
return None
def get_center_pts(bbox, np_array = False):
if bbox is not None:
center = 0.5*(bbox[0] + bbox[1]), 0.5*(bbox[2] + bbox[3])
if np_array:
center = np.asarray(center)
else:
center = np.asarray([0,0])
return center