File size: 3,458 Bytes
6062b47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
103
104
105
106
107
108
109
110
111
112
113
114
"""Camera angle data structures for Fibo Edit."""

from dataclasses import dataclass
from enum import Enum


class View(Enum):
    """Camera view angles"""
    BACK_VIEW = "back view"
    BACK_LEFT_QUARTER = "back-left quarter view"
    BACK_RIGHT_QUARTER = "back-right quarter view"
    FRONT_VIEW = "front view"
    FRONT_LEFT_QUARTER = "front-left quarter view"
    FRONT_RIGHT_QUARTER = "front-right quarter view"
    LEFT_SIDE = "left side view"
    RIGHT_SIDE = "right side view"


class Shot(Enum):
    """
    Camera shot angles (measured from horizontal/eye-level as 0 degrees)

    - ELEVATED: 45-60 degrees above subject (moderately elevated)
    - EYE_LEVEL: 0 degrees (horizontal with subject)
    - HIGH_ANGLE: 60-90 degrees above subject (steep overhead, bird's eye)
    - LOW_ANGLE: Below eye level (looking up at subject)
    """
    ELEVATED = "elevated shot"
    EYE_LEVEL = "eye-level shot"
    HIGH_ANGLE = "high-angle shot"
    LOW_ANGLE = "low-angle shot"


class Zoom(Enum):
    """Camera zoom levels"""
    CLOSE_UP = "close-up"
    MEDIUM = "medium shot"
    WIDE = "wide shot"


@dataclass
class AngleInstruction:
    view: View
    shot: Shot
    zoom: Zoom

    def __str__(self):
        return f"<sks> {self.view.value} {self.shot.value} {self.zoom.value}"

    @classmethod
    def from_camera_params(cls, rotation: float, tilt: float, zoom: float) -> "AngleInstruction":
        """
        Create an AngleInstruction from camera parameters.

        Args:
            rotation: Horizontal rotation in degrees (-180 to 180)
                     -180/180: back view, -90: left view, 0: front view, 90: right view
            tilt: Vertical tilt (-1 to 1)
                  -1 to -0.33: low-angle shot
                  -0.33 to 0.33: eye-level shot
                  0.33 to 0.66: elevated shot
                  0.66 to 1: high-angle shot
            zoom: Zoom level (0 to 10)
                  0-3.33: wide shot
                  3.33-6.66: medium shot
                  6.66-10: close-up

        Returns:
            AngleInstruction instance
        """
        # Map rotation to View
        # Normalize rotation to -180 to 180 range
        rotation = rotation % 360
        if rotation > 180:
            rotation -= 360

        # Determine view based on rotation
        if -157.5 <= rotation < -112.5:
            view = View.BACK_LEFT_QUARTER
        elif -112.5 <= rotation < -67.5:
            view = View.LEFT_SIDE
        elif -67.5 <= rotation < -22.5:
            view = View.FRONT_LEFT_QUARTER
        elif -22.5 <= rotation < 22.5:
            view = View.FRONT_VIEW
        elif 22.5 <= rotation < 67.5:
            view = View.FRONT_RIGHT_QUARTER
        elif 67.5 <= rotation < 112.5:
            view = View.RIGHT_SIDE
        elif 112.5 <= rotation < 157.5:
            view = View.BACK_RIGHT_QUARTER
        else:  # 157.5 to 180 or -180 to -157.5
            view = View.BACK_VIEW

        # Map tilt to Shot
        if tilt < -0.33:
            shot = Shot.LOW_ANGLE
        elif tilt < 0.33:
            shot = Shot.EYE_LEVEL
        elif tilt < 0.66:
            shot = Shot.ELEVATED
        else:
            shot = Shot.HIGH_ANGLE

        # Map zoom to Zoom
        if zoom < 3.33:
            zoom_level = Zoom.WIDE
        elif zoom < 6.66:
            zoom_level = Zoom.MEDIUM
        else:
            zoom_level = Zoom.CLOSE_UP

        return cls(view=view, shot=shot, zoom=zoom_level)