NaraMotion / tests /test_cinematic_engine.py
ArifiIslam's picture
Release NaraMotion v0.26.0: Structure of Arrays (SoA), Path Arena Allocator, Uniform Grid Indexing, Dual-Buffer Rendering & Centroid Spring Pop-in
b516e00 verified
Raw History Blame Contribute Delete
3.3 kB
import math
import pytest
import shapely
from shapely.geometry import Polygon, LineString, Point
import geopandas as gpd
import naramotion as nm
from naramotion import (
Image, Context, Format,
compute_center, get_center, get_centroid,
Palette,
tone_map_aces, tone_map_reinhard
)
from naramotion.shapgeo import GeoCanvas, GeoTransform
from naramotion.motion import Spring, DrawReveal, Typewriter, Stagger
from naramotion.path import Path
def test_compute_center_and_centroids():
# 1. Bounds tuple (minx, miny, maxx, maxy)
bounds = (10.0, 20.0, 30.0, 40.0)
cx, cy = compute_center(bounds)
assert cx == 20.0
assert cy == 30.0
# 2. Shapely Polygon
poly = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)])
cx, cy = get_center(poly)
assert math.isclose(cx, 5.0)
assert math.isclose(cy, 5.0)
# 3. GeoDataFrame
gdf = gpd.GeoDataFrame({
"name": ["A", "B"],
"geometry": [Point(0, 0), Point(10, 20)]
})
cx, cy = get_centroid(gdf)
assert math.isclose(cx, 5.0)
assert math.isclose(cy, 10.0)
# 4. Path
p = Path()
p.add_rect(100, 100, 200, 200) # (100, 100) to (300, 300)
cx, cy = compute_center(p)
assert math.isclose(cx, 200.0)
assert math.isclose(cy, 200.0)
def test_geocanvas_center_and_dynamic_stroke():
with GeoCanvas(width=800, height=600, bounds=(0, 0, 100, 100)) as canvas:
cx, cy = canvas.center
assert math.isclose(cx, 50.0)
assert math.isclose(cy, 50.0)
# Focus on a specific point
canvas.focus_on((20.0, 30.0, 40.0, 50.0), zoom=2.0)
fcx, fcy = canvas.center
assert math.isclose(fcx, 30.0)
assert math.isclose(fcy, 40.0)
# Dynamic stroke test
w = canvas._calc_stroke_width(2.0, dynamic_stroke=True)
assert 0.25 <= w <= 12.0
def test_palettes_and_color_harmony():
# Built-in palette
cyber = Palette.get("cyberpunk")
assert len(cyber) >= 5
tokyo = Palette.get("tokyo_night")
assert len(tokyo) >= 5
# Harmonic generator
colors = Palette.generate(8, base_color="#00F0FF", mode="golden_ratio")
assert len(colors) == 8
# Ensure distinct colors
values = set(c.value for c in colors)
assert len(values) == 8
def test_aces_tone_mapping_and_bloom():
img = Image(200, 200, Format.PRGB32)
with Context(img) as ctx:
ctx.fill_all("#FF007F") # Hot pink
# Apply ACES tone mapping
tone_map_aces(img, exposure=1.2)
tone_map_reinhard(img, exposure=1.0)
assert img.width == 200
def test_spring_and_declarative_actions():
# Spring physics
spring = Spring(stiffness=200, damping=10)
val_start = spring.evaluate(0.0)
val_end = spring.evaluate(1.0)
assert math.isclose(val_start, 0.0, abs_tol=0.01)
assert math.isclose(val_end, 1.0, abs_tol=0.1)
# Actions
p = Path()
p.add_circle(100, 100, 50)
act1 = DrawReveal(p, duration=1.0, delay=0.2)
act2 = Typewriter("TEST TEXT", x=50, y=50, duration=1.0)
staggered = Stagger.create([act1, act2], delay_step=0.5)
assert staggered[0].delay == 0.2
assert math.isclose(staggered[1].delay, 0.5)
img = Image(400, 400, Format.PRGB32)
with Context(img) as ctx:
act1.render(0.5, ctx)
act2.render(0.8, ctx)