Skip to content

Commit

Permalink
add Vector.direction360
Browse files Browse the repository at this point in the history
  • Loading branch information
cdzombak committed May 25, 2024
1 parent 0266377 commit e0a8a7b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 8 deletions.
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ The origin for box coordinates `(0, 0)` is the top-left corner of the frame. Coo

#### Movement vector

A track's movement vector is calculated from the center of the prediction box at the start of the track, to the center of the most recent prediction box in the track. It has two properties, `length` and `direction`.
A track's movement vector is calculated from the center of the prediction box at the start of the track, to the center of the most recent prediction box in the track. It has three properties: `length`, `direction`, and `direction360`.

##### `length`

Expand Down Expand Up @@ -293,9 +293,11 @@ A length of `1` would cover the entire frame vertically or horizontally; a lengt

The direction of the vector, in degrees, from `[-180, 180)`.

`0°` is straight to the right of frame; `90º` is straight up; `-180º` is straight left; `-90º` is straight down:
`0°` is straight to the **right** of frame; `90º` is straight **up**; `-180º` is straight **left**; `-90º` is straight **down**:

```text
direction of a vector from point a to b:
┌───┐
│ b │
┌───┐ └─▲─┘ ┌───┐
Expand All @@ -317,6 +319,36 @@ The direction of the vector, in degrees, from `[-180, 180)`.
└───┘
```

##### `direction360`

The direction of the vector, in degrees, from `[0, 360)`. This is just `direction + 180`, but depending on the video in your use case, it may be more convenient to work with this figure instead of `direction`.

`0°` is straight to the **left** of frame; `90º` is straight **down**; `180º` is straight **right**; `270º` is straight **up**:

```text
direction360 of a vector from point a to b:
┌───┐
│ b │
┌───┐ └─▲─┘ ┌───┐
│ b │ │ │ b │
└─▲─┘ 270º └─▲─┘
╲ │ ╱
315º╲ │ 225º
╳───┴───╳
┌───┐ │ │ 180º┌───┐
│ b ◀──────┤ a │──────▶ b │
└───┘ 0º │ │ └───┘
╳───┬───╳
45º ╱ │ ╲135º
╱ │ ╲
┌─▼─┐ 90º ┌─▼─┐
│ b │ │ │ b │
└───┘ ┌─▼─┐ └───┘
│ b │
└───┘
```

#### Example

Here's an example expression that I use at home:
Expand Down
Binary file added doc/vector-direction360.monopic
Binary file not shown.
6 changes: 5 additions & 1 deletion lib_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class Vector:
# │ b │
# └───┘
direction: float
direction360: float
length: float

def to_cel(self) -> celpy.celtypes.Value:
Expand All @@ -128,6 +129,7 @@ def to_cel(self) -> celpy.celtypes.Value:
return celpy.celtypes.MapType(
{
"direction": celpy.celtypes.DoubleType(self.direction),
"direction360": celpy.celtypes.DoubleType(self.direction360),
"length": celpy.celtypes.DoubleType(self.length),
}
)
Expand All @@ -136,7 +138,9 @@ def to_cel(self) -> celpy.celtypes.Value:
def from_points(a: Point, b: Point) -> "Vector":
dx = b.x - a.x
dy = b.y - a.y
direct = -1 * math.degrees(math.atan2(dy, dx))
return Vector(
length=(dx**2 + dy**2) ** 0.5,
direction=-1 * math.degrees(math.atan2(dy, dx)),
direction=direct,
direction360=direct + 180.0,
)
13 changes: 8 additions & 5 deletions tests/test_lib_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
class TestVector(TestCase):
def test_from_points(self):
v = Vector.from_points(Point(0, 0), Point(0, 0)) # no movement
self.assertEqual(Vector(length=0, direction=0), v)
self.assertEqual(Vector(length=0, direction=0, direction360=180), v)

v = Vector.from_points(Point(0, 1), Point(0, 0)) # straight up
self.assertEqual(Vector(length=1, direction=90), v)
self.assertEqual(Vector(length=1, direction=90, direction360=270), v)

v = Vector.from_points(Point(0, 0), Point(0, 1)) # straight down
self.assertEqual(Vector(length=1, direction=-90), v)
self.assertEqual(Vector(length=1, direction=-90, direction360=90), v)

v = Vector.from_points(Point(1, 0), Point(0, 0)) # straight left
self.assertEqual(Vector(length=1, direction=-180), v)
self.assertEqual(Vector(length=1, direction=-180, direction360=0), v)

v = Vector.from_points(Point(0, 0), Point(1, 0)) # straight right
self.assertEqual(Vector(length=1, direction=0), v)
self.assertEqual(Vector(length=1, direction=0, direction360=180), v)

v = Vector.from_points(Point(1, 2), Point(0, 1)) # up and to the left
self.assertEqual(135, v.direction)
self.assertEqual(315, v.direction360)
self.assertTrue(float_eq(1.414, v.length), f"(got {v.length}")

v = Vector.from_points(Point(0, 2), Point(1, 1)) # up and to the right
Expand All @@ -30,10 +31,12 @@ def test_from_points(self):

v = Vector.from_points(Point(2, 1), Point(1, 2)) # down and to the left
self.assertEqual(-135, v.direction)
self.assertEqual(45, v.direction360)
self.assertTrue(float_eq(1.414, v.length), f"(got {v.length}")

v = Vector.from_points(Point(1, 1), Point(2, 2)) # down and to the right
self.assertEqual(-45, v.direction)
self.assertEqual(135, v.direction360)
self.assertTrue(float_eq(1.414, v.length), f"(got {v.length}")


Expand Down

0 comments on commit e0a8a7b

Please sign in to comment.