# -*- coding: utf-8 -*-
"""
统一渲染器
- 在图像上绘制点云（支持透明度、方形像素块）
- 仅负责渲染，不做过滤或投影
"""

import cv2
import numpy as np
from typing import Tuple


class PointCloudRenderer:
    """点云渲染器：在图像上绘制点云"""

    def draw_points(
        self,
        image: np.ndarray,
        points_2d: np.ndarray,
        colors: np.ndarray,
        point_size: int = 2,
        point_opacity: float = 1.0,
    ) -> np.ndarray:
        """
        在图像上绘制点云（支持透明度，方形像素块）

        Args:
            image: 输入图像 (H, W, 3)
            points_2d: Nx2 像素坐标 (u, v)
            colors: Nx3 颜色 (B, G, R)
            point_size: 点大小（像素，方形块）
            point_opacity: 不透明度 [0, 1]

        Returns:
            绘制后的图像
        """
        if image is None or len(points_2d) == 0:
            return image

        result = image.copy()
        h, w = result.shape[:2]

        if point_opacity >= 0.99:
            self._draw_opaque(result, points_2d, colors, point_size, w, h)
        else:
            overlay = result.copy()
            self._draw_opaque(overlay, points_2d, colors, point_size, w, h)
            cv2.addWeighted(overlay, point_opacity, result, 1 - point_opacity, 0, result)

        return result

    def _draw_opaque(
        self,
        canvas: np.ndarray,
        points_2d: np.ndarray,
        colors: np.ndarray,
        point_size: int,
        width: int,
        height: int,
    ) -> None:
        """在 canvas 上直接绘制（不做透明度混合）"""
        for i, (u, v) in enumerate(points_2d):
            color = tuple(map(int, colors[i]))

            if point_size == 1:
                if 0 <= v < height and 0 <= u < width:
                    canvas[v, u] = color
            else:
                if point_size % 2 == 0:
                    x_start, y_start = u, v
                    x_end, y_end = u + point_size, v + point_size
                else:
                    half = point_size // 2
                    x_start = u - half
                    y_start = v - half
                    x_end = u + half + 1
                    y_end = v + half + 1

                x_start = max(0, x_start)
                y_start = max(0, y_start)
                x_end = min(width, x_end)
                y_end = min(height, y_end)

                if x_start < x_end and y_start < y_end:
                    canvas[y_start:y_end, x_start:x_end] = color
