Axiovora-X / demo.py
ZAIDX11's picture
Add files using upload-large-folder tool
bb85593 verified
"""Demo module expanded for safe demo.
This module provides a compact geometry/vector utility library used by the
demo test. It's self-contained, pure Python, and intended to be safe to add
to the repository without changing any project-wide dependencies.
The file intentionally contains a variety of helper functions and small
classes to simulate a larger, realistic module while remaining easy to
understand and test.
"""
from __future__ import annotations
import math
import random
from typing import Iterable, List, Tuple
class Vector:
"""A small immutable 2D vector class with utility methods."""
__slots__ = ("x", "y")
def __init__(self, x: float, y: float) -> None:
self.x = float(x)
self.y = float(y)
def __iter__(self):
yield self.x
yield self.y
def __repr__(self) -> str: # pragma: no cover - trivial
return f"Vector({self.x:.4f}, {self.y:.4f})"
def __add__(self, other: "Vector") -> "Vector":
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other: "Vector") -> "Vector":
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar: float) -> "Vector":
return Vector(self.x * scalar, self.y * scalar)
def dot(self, other: "Vector") -> float:
return self.x * other.x + self.y * other.y
def cross(self, other: "Vector") -> float:
"""2D cross product (scalar) used for orientation tests."""
return self.x * other.y - self.y * other.x
def length(self) -> float:
return math.hypot(self.x, self.y)
def normalized(self) -> "Vector":
l = self.length()
if l == 0:
return Vector(0.0, 0.0)
return Vector(self.x / l, self.y / l)
def rotate(self, angle_rad: float) -> "Vector":
"""Rotate vector counter-clockwise by angle in radians."""
c = math.cos(angle_rad)
s = math.sin(angle_rad)
return Vector(self.x * c - self.y * s, self.x * s + self.y * c)
def polygon_area(points: Iterable[Vector]) -> float:
"""Compute polygon area using the shoelace formula.
Works for convex and non-convex polygons (signed area).
"""
pts = list(points)
if len(pts) < 3:
return 0.0
area = 0.0
for i in range(len(pts)):
a = pts[i]
b = pts[(i + 1) % len(pts)]
area += a.x * b.y - a.y * b.x
return 0.5 * abs(area)
def centroid(points: Iterable[Vector]) -> Vector:
pts = list(points)
if not pts:
return Vector(0.0, 0.0)
sx = sum(p.x for p in pts)
sy = sum(p.y for p in pts)
n = len(pts)
return Vector(sx / n, sy / n)
def is_convex_polygon(points: Iterable[Vector]) -> bool:
pts = list(points)
if len(pts) < 4:
return True
sign = 0
n = len(pts)
for i in range(n):
a = pts[i]
b = pts[(i + 1) % n]
c = pts[(i + 2) % n]
cross = (b - a).cross(c - b)
if cross != 0:
s = 1 if cross > 0 else -1
if sign == 0:
sign = s
elif sign != s:
return False
return True
def bounding_box(points: Iterable[Vector]) -> Tuple[Vector, Vector]:
pts = list(points)
if not pts:
return Vector(0.0, 0.0), Vector(0.0, 0.0)
minx = min(p.x for p in pts)
miny = min(p.y for p in pts)
maxx = max(p.x for p in pts)
maxy = max(p.y for p in pts)
return Vector(minx, miny), Vector(maxx, maxy)
def generate_random_polygon(n: int, radius: float = 1.0, seed: int | None = None) -> List[Vector]:
"""Generate a simple random star-like polygon (not guaranteed simple).
This is intentionally simple for the demo and is not intended as a
production polygon generator.
"""
if seed is not None:
random.seed(seed)
angles = sorted(random.random() * 2 * math.pi for _ in range(n))
pts = [Vector(math.cos(a) * radius * (0.5 + random.random() / 2),
math.sin(a) * radius * (0.5 + random.random() / 2))
for a in angles]
return pts
# A few small convenience aliases used by the test harness.
def make_vector(x: float, y: float) -> Vector:
return Vector(x, y)
def rotate_polygon(points: Iterable[Vector], angle_rad: float) -> List[Vector]:
return [p.rotate(angle_rad) for p in points]
def translate_polygon(points: Iterable[Vector], offset: Vector) -> List[Vector]:
return [p + offset for p in points]
# The following block creates a collection of small deterministic utility
# functions to expand the file size for the demo. Each function is tiny
# and deterministic; they are real code and are useful for tests.
def _make_op(i: int):
def op(x: float, y: float) -> float:
# simple deterministic but non-trivial computation
a = x + (i % 5) * 0.1
b = y - (i % 7) * 0.07
return (a * a + b * b) ** 0.5 + (i % 3) * 0.001
op.__name__ = f"op_{i}"
return op
# Create and expose a number of small operations.
_OPS = {f"op_{i}": _make_op(i) for i in range(1, 201)}
def apply_ops(x: float, y: float) -> List[float]:
"""Apply all small ops to the given inputs and return results.
Used by tests to verify the demo module behaves deterministically.
"""
return [fn(x, y) for fn in _OPS.values()]
def demo_example(seed: int = 42) -> dict:
"""Return a deterministic demo payload used by tests and CLI.
The payload includes a generated polygon, its area and centroid, and
a short list of op results to verify deterministic behavior.
"""
poly = generate_random_polygon(6, radius=1.5, seed=seed)
area = polygon_area(poly)
cent = centroid(poly)
ops = apply_ops(0.5, -0.25)[:5]
return {
"area": area,
"centroid": (cent.x, cent.y),
"ops": ops,
}
def demo_run_cli() -> None:
"""Simple CLI runner used when demo.py is executed as a script."""
payload = demo_example()
print("Demo payload:")
print(f" area={payload['area']:.6f}")
print(f" centroid={payload['centroid']}")
print(" ops:")
for v in payload["ops"]:
print(f" - {v:.6f}")
if __name__ == "__main__": # pragma: no cover - simple CLI
poly = generate_random_polygon(8, radius=2.0, seed=42)
print("Polygon area:", polygon_area(poly))
print("Centroid:", centroid(poly))
print("Is convex:", is_convex_polygon(poly))