1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import numpy as np
import math
import scipy.misc as m

class ProjectionGenerator():
    """
    Generates projection between original 3D space and rendered 2D image space
    Given the position of the room
    """
    def __init__(self, room_size_cap=(6.05,4.05,6.05), zpad=0.5, img_size=512):
        """
        See top_down.TopDownView for explanation of room_size, zpad and img_size
        """
        self.room_size_cap = room_size_cap
        self.zpad = zpad
        self.img_size = img_size
        self.xscale = self.img_size / self.room_size_cap[0]
        self.yscale = self.img_size / self.room_size_cap[2]
        self.zscale = 1.0 / (self.room_size_cap[1] + self.zpad)

    def get_projection(self, room):
        """
        Generates projection matrices specific to a room,
        need to be room-specific since every room is located in a different position,
        but they are all rendered centered in the image
        """
        xscale, yscale, zscale = self.xscale, self.yscale, self.zscale

        xshift = -(room.xmin * 0.5 + room.xmax * 0.5 - self.room_size_cap[0] / 2.0)
        yshift = -(room.ymin * 0.5 + room.ymax * 0.5 - self.room_size_cap[2] / 2.0)
        zshift = -room.zmin + self.zpad

        t_scale = np.asarray([[xscale, 0, 0, 0], \
                              [0, zscale, 0, 0], \
                              [0, 0, yscale, 0], \
                              [0, 0, 0, 1]])
        
        t_shift = np.asarray([[1, 0, 0, 0], \
                              [0, 1, 0, 0], \
                              [0, 0, 1, 0], \
                              [xshift, zshift, yshift, 1]])

        t_3To2 = np.dot(t_shift, t_scale)
    
        t_scale = np.asarray([[1/xscale, 0, 0, 0], \
                              [0, 1/zscale, 0, 0], \
                              [0, 0, 1/yscale, 0], \
                              [0, 0, 0, 1]])
        
        t_shift = np.asarray([[1, 0, 0, 0], \
                              [0, 1, 0, 0], \
                              [0, 0, 1, 0], \
                              [-xshift, -zshift, -yshift, 1]])
        
        t_2To3 = np.dot(t_scale, t_shift)

        return Projection(t_3To2, t_2To3, self.img_size)

class Projection():
    def __init__(self, t_2d, t_3d, img_size):
        self.t_2d = t_2d
        self.t_3d = t_3d
        self.img_size = img_size
    
    def to_2d(self, t=None):
        """
        Parameters
        ----------
        t(Matrix or None): transformation matrix of the object
            if None, then returns room projection
        """
        if t is None:
            return self.t_2d
        else:
            return np.dot(t, self.t_2d)

    def to_3d(self, t=None):
        if t is None:
            return self.t_3d
        else:
            return np.dot(t, self.t_3d)

    def get_ortho_parameters(self):
        bottom_left = np.asarray([0,0,0,1])
        top_right = np.asarray([self.img_size,1,self.img_size,1])
        bottom_left = np.dot(bottom_left, self.t_3d)
        top_right = np.dot(top_right, self.t_3d)
        return (bottom_left[0], top_right[0], bottom_left[2], top_right[2], bottom_left[1], top_right[1])