Files
rk_pve/pve/polygon.py
2025-10-24 05:26:42 +02:00

108 lines
3.7 KiB
Python

# People's Video Editor: high quality, GPU accelerated mp4 editor
# Copyright (C) 2025 Roz K <roz@rozk.net>
#
# This file is part of People's Video Editor.
#
# People's Video Editor is free software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# People's Video Editor is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with People's Video Editor.
# If not, see <https://www.gnu.org/licenses/>.
from array import array
from .node import Node
from .vector import Vector2
class Point:
__slots__ = 'position', 'mapping'
def __init__(self, xy = Vector2(), uv = Vector2()):
assert isinstance(xy, Vector2) and isinstance(uv, Vector2)
self.position = xy
self.mapping = uv
class Polygon(Node):
__slots__ = '_positions', '_mappings', '_len'
@classmethod
def rectangle(cls, geometry):
tl = Vector2(0.0, 0.0)
tr = Vector2(geometry._width, 0.0)
br = Vector2(geometry._width, geometry._height)
bl = Vector2(0.0, geometry._height)
return cls(points = (
Point(tl, tl),
Point(tr, tr),
Point(br, br),
Point(bl, bl)))
def __init__(self, parent = None, children = None, size = 0, points = None):
Node.__init__(self, parent, children)
self.clear_points()
self.add_points(size, points)
def __len__(self):
return self._len
def __getitem__(self, index):
begin = index * 2
end = begin + 2
return Point(
Vector2(*self._positions[begin:end]),
Vector2(*self._mappings[begin:end]))
def __setitem__(self, index, point):
begin = index * 2
end = begin + 2
self._positions[begin:end] = array(Vector2.TYPE, point.position)
self._mappings[begin:end] = array(Vector2.TYPE, point.mapping)
def add_child(self, child):
assert isinstance(child, Polygon)
Node.add_child(self, child)
def add_points(self, count = 0, points = None):
assert (count > 0) ^ len(points)
if count:
initializer = bytes(count * Vector2.SIZE)
self._positions.frombytes(initializer)
self._mappings.frombytes(initializer)
self._len += count
else:
for point in points:
self._positions.extend(point.position)
self._mappings.extend(point.mapping)
self._len += len(points)
def insert_points(self, index, count = 0, points = None):
assert (count == 0) ^ (points is None)
index *= 2
if count:
initializer = array(Vector2.TYPE, bytes(count * Vector2.SIZE))
self._positions[index:index] = initializer
self._mappings[index:index] = initializer
self._len += count
else:
polygon = Polygon(points = points)
self._positions[index:index] = polygon._positions
self._mappings[index:index] = polygon._mappings
self._len += polygon._len
def remove_points(self, index, count = 1):
begin = index * 2
end = begin + count * 2
del self._positions[begin:end]
del self._mappings[begin:end]
self._len -= count
def clear_points(self):
self._positions = array(Vector2.TYPE)
self._mappings = array(Vector2.TYPE)
self._len = 0