# src/layout_generator/base.py """ Базовые структуры данных и абстрактные классы для пайплайна генерации. Определяет контекст состояния (LayoutContext) и интерфейс шагов (BaseStep). """ from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import Any, Dict, List, Optional import trimesh from omegaconf import DictConfig from utils.logger import CollisionTracker from dsynth.scene_gen.utils import RectFixture @dataclass class LayoutContext: """Объект состояния, передаваемый между шагами генерации.""" project_dir: str = "" size_n: int = 10 size_m: int = 10 # Главный источник истины от LLM layout_graph: Optional[Dict[str, Any]] = None cfg: Optional[DictConfig] = None tracker: Optional[CollisionTracker] = None # Кэш 3D-моделей в ОЗУ product_assets_lib: Dict[str, Any] = field(default_factory=dict) # Данные из шага 2 (Планограмма) fixed_zones: Any = None product_filling: Dict[str, Any] = field(default_factory=dict) nodes_dict: Dict[str, RectFixture] = field(default_factory=dict) # Метрики для экспортера report_matrix: Dict[str, Any] = field(default_factory=dict) total_shelves: int = 0 # Данные из шага 3 и 4 (Топология и Сборка) is_gen: bool = False placed_fixtures: List[RectFixture] = field(default_factory=list) current_seed: int = 0 final_scene: Optional[trimesh.Scene] = None actual_shelf_idx: int = 0 output_filename: str = "" class BaseStep(ABC): """Абстрактный класс шага пайплайна.""" @abstractmethod def process(self, context: LayoutContext) -> LayoutContext: """ Выполняет изолированную логику шага. Args: context (LayoutContext): Текущее состояние генерации. Returns: LayoutContext: Обновленное состояние. """ pass