Source code for flexcompute.flow_report.scene

"""Read-only cloud resource for reusable Flow360 visualization scenes."""

from __future__ import annotations

from typing import Any, Literal

import pydantic as pd

from . import models
from ._flow360_adapter import DEFAULT_FLOW360_ADAPTER, Flow360Adapter


class SceneVisualizationPayload(models.VisualizationViewSetup):
    """Versioned Workbench visualization setting stored by a Scene."""

    schema_version: Literal[1]

    def _as_report_setup(self) -> models.VisualizationViewSetup:
        return models.VisualizationViewSetup.model_validate(
            self.model_dump(exclude={"schema_version"})
        )


class SceneViewpointPayload(models.ReportCameraParams):
    """Versioned camera stored by a Scene in canonical metres."""

    schema_version: Literal[1]

    def _as_report_camera(self) -> models.ReportCameraParams:
        return models.ReportCameraParams.model_validate(self.model_dump(exclude={"schema_version"}))


class SceneVisualizationSetting(models.ReportBaseModel):
    """Visualization setting returned with a Scene."""

    id: str = pd.Field(min_length=1)
    project_id: str = pd.Field(min_length=1)
    resource_type: models.ResourceType
    resource_item_id: str = pd.Field(min_length=1)
    payload: SceneVisualizationPayload

    def _as_report_setup(self) -> models.VisualizationViewSetup:
        return self.payload._as_report_setup()


class SceneViewpoint(models.ReportBaseModel):
    """Viewpoint returned with a Scene."""

    id: str = pd.Field(min_length=1)
    project_id: str = pd.Field(min_length=1)
    payload: SceneViewpointPayload

    def _as_report_camera(self) -> models.ReportCameraParams:
        return self.payload._as_report_camera()


class _SceneInfo(models.ReportBaseModel):
    """Complete response returned by ``GET /v2/scenes/{sceneId}``."""

    id: str = pd.Field(min_length=1)
    project_id: str = pd.Field(min_length=1)
    name: str = pd.Field(min_length=1)
    resource_type: models.ResourceType
    resource_item_id: str = pd.Field(min_length=1)
    created_at: int
    updated_at: int
    created_by: str = pd.Field(min_length=1)
    updated_by: str = pd.Field(min_length=1)
    visualization_setting: SceneVisualizationSetting
    viewpoint: SceneViewpoint

    @pd.model_validator(mode="after")
    def _validate_child_metadata(self):
        setting = self.visualization_setting
        if setting.project_id != self.project_id:
            raise ValueError("scene visualization setting belongs to a different project")
        if setting.resource_type != self.resource_type:
            raise ValueError("scene visualization setting has a different resource type")
        if setting.resource_item_id != self.resource_item_id:
            raise ValueError("scene visualization setting belongs to a different resource item")
        if self.viewpoint.project_id != self.project_id:
            raise ValueError("scene viewpoint belongs to a different project")
        return self


[docs] class Scene: """A read-only visualization Scene loaded from the active Flow360 environment.""" _cloud_resource_type_name = "Scene" _adapter = DEFAULT_FLOW360_ADAPTER def __init__( self, *, info: _SceneInfo, environment: Any, adapter: Flow360Adapter, ): self._info = info self._environment = environment self._flow360_adapter = adapter
[docs] @classmethod def from_cloud(cls, scene_id: str) -> "Scene": """Load a Scene and its visualization setting and viewpoint. Before applying ``visualization_setting`` to multiple resources, obtain each resource's capabilities and call ``check_visualization_setup`` before creating or updating the Report. """ if not isinstance(scene_id, str): raise TypeError("scene_id must be a string") normalized_scene_id = scene_id.strip() if not normalized_scene_id: raise ValueError("scene_id must not be empty") adapter = cls._adapter environment = adapter.current_environment() response = adapter.get_scene(normalized_scene_id, environment=environment) return cls( info=_SceneInfo.model_validate(response), environment=environment, adapter=adapter, )
@property def id(self) -> str: """Cloud Scene ID.""" return self._info.id @property def project_id(self) -> str: """Project containing this Scene.""" return self._info.project_id @property def name(self) -> str: """Scene name.""" return self._info.name @property def resource_type(self) -> models.ResourceType: """Resource type from which the Scene setting was captured.""" return self._info.resource_type @property def resource_item_id(self) -> str: """Resource ID from which the Scene setting was captured.""" return self._info.resource_item_id @property def created_by(self) -> str: """User ID that created this Scene.""" return self._info.created_by @property def updated_by(self) -> str: """User ID that last updated this Scene.""" return self._info.updated_by @property def created_at(self) -> int: """Scene creation timestamp returned by the API.""" return self._info.created_at @property def updated_at(self) -> int: """Scene update timestamp returned by the API.""" return self._info.updated_at @property def visualization_setting(self) -> SceneVisualizationSetting: """A defensive copy of the Scene's Workbench visualization setting.""" return self._info.visualization_setting.model_copy(deep=True) @property def viewpoint(self) -> SceneViewpoint: """A defensive copy of the Scene's canonical-metre viewpoint.""" return self._info.viewpoint.model_copy(deep=True) def __repr__(self) -> str: return f"Scene(id={self.id!r}, name={self.name!r}, resource_type={self.resource_type!r})"