summaryrefslogtreecommitdiff
path: root/aabb.py
blob: d913143a4737c8ca585f9baa379eedf92ea26690 (plain) (blame)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import numpy as np
from utils import quat2rot

def aabb_size(scale, rotation, scale_factor=1):
    scale = scale_factor * scale
    if scale.shape != (3, 3):
        scale_matrix = np.diag(scale)
    else:
        scale_matrix = scale
    
    if rotation.shape != (3, 3):
        rotation = rotation / np.linalg.norm(rotation)
        rotation_matrix = quat2rot(rotation)
        # r, x, y, z = rotation[0], rotation[1], rotation[2], rotation[3]
        # rotation_matrix = np.array([
        #     [1. - 2. * (y * y + z * z), 2. * (x * y - r * z), 2. * (x * z + r * y)],
        #     [2. * (x * y + r * z), 1. - 2. * (x * x + z * z), 2. * (y * z - r * x)],
        #     [2. * (x * z - r * y), 2. * (y * z + r * x), 1. - 2. * (x * x + y * y)]
        # ], dtype=np.float32)
    else:
        rotation_matrix = rotation

    M = scale_matrix @ rotation_matrix
    R = M.T @ M

    x_span = np.sqrt(R[0][0])
    y_span = np.sqrt(R[1][1])
    z_span = np.sqrt(R[2][2])

    return x_span, y_span, z_span

def process_aabb(position, scale, rotation, scale_factor=1):
    x_span, y_span, z_span = aabb_size(scale, rotation, scale_factor)

    xmin = position[0] - x_span
    xmax = position[0] + x_span
    ymin = position[1] - y_span
    ymax = position[1] + y_span
    zmin = position[2] - z_span
    zmax = position[2] + z_span
    
    aabb = np.array([xmin, xmax, ymin, ymax, zmin, zmax])
    if np.isnan(aabb).any():
        print("nan detected!")
        print(scale, rotation, aabb)

    return aabb

def solve_scale(rotation, aabb):
    dest = np.array([
        (aabb[1] - aabb[0]) * (aabb[1] - aabb[0]) / 4,
        (aabb[3] - aabb[2]) * (aabb[3] - aabb[2]) / 4,
        (aabb[5] - aabb[4]) * (aabb[5] - aabb[4]) / 4,
    ])

    rotation = rotation / np.linalg.norm(rotation)
    r, x, y, z = rotation[0], rotation[1], rotation[2], rotation[3]
    rotation_matrix = np.array([
        [1. - 2. * (y * y + z * z), 2. * (x * y - r * z), 2. * (x * z + r * y)],
        [2. * (x * y + r * z), 1. - 2. * (x * x + z * z), 2. * (y * z - r * x)],
        [2. * (x * z - r * y), 2. * (y * z + r * x), 1. - 2. * (x * x + y * y)]
    ], dtype=np.float32)

    coeff = rotation_matrix.T * rotation_matrix.T
    solution = np.linalg.solve(coeff, dest)
    print(solution)
    return np.sqrt(solution)


def intersect(aabb1, aabb2):
    new_aabb = np.zeros_like(aabb1)
    new_aabb[0] = max(aabb1[0], aabb2[0])
    new_aabb[1] = min(aabb1[1], aabb2[1])
    new_aabb[2] = max(aabb1[2], aabb2[2])
    new_aabb[3] = min(aabb1[3], aabb2[3])
    new_aabb[4] = max(aabb1[4], aabb2[4])
    new_aabb[5] = min(aabb1[5], aabb2[5])

    if new_aabb[0] < new_aabb[1] and new_aabb[2] < new_aabb[3] and new_aabb[4] < new_aabb[5]:
        return new_aabb
    else:
        return None

def aabb_merge(aabb1, aabb2):
    new_aabb = np.zeros_like(aabb1)
    new_aabb[0] = min(aabb1[0], aabb2[0])
    new_aabb[1] = max(aabb1[1], aabb2[1])
    new_aabb[2] = min(aabb1[2], aabb2[2])
    new_aabb[3] = max(aabb1[3], aabb2[3])
    new_aabb[4] = min(aabb1[4], aabb2[4])
    new_aabb[5] = max(aabb1[5], aabb2[5])
    return new_aabb

def center(aabb):
    return np.array([
        aabb[0] + aabb[1],
        aabb[2] + aabb[3],
        aabb[4] + aabb[5]
    ]) / 2

def min_interval(aabb):
    return min(aabb[1] - aabb[0], min(aabb[3] - aabb[2], aabb[5] - aabb[4]))