Source code for gefest.core.geometry.domain

from typing import Optional, Union

from pydantic import BaseModel, Field, computed_field, field_validator, model_validator

from gefest.core.geometry import Point, Polygon, Structure
from gefest.core.geometry.geometry_2d import Geometry, Geometry2D
from gefest.core.utils.functions import parse_structs


[docs] class Domain(BaseModel): """Domain configuration dataclass.""" allowed_area: Union[Polygon, list[list[float]]] name: str = 'main' min_poly_num: int = 2 max_poly_num: int = 4 min_points_num: int = 20 max_points_num: int = 50 polygon_side: float = 0.0001 min_dist_from_boundary: float = 0.0001 prohibited_area: Optional[Union[Structure, str]] = Field(default=Structure()) fixed_points: Optional[Union[Polygon, list[list[float]]]] = Field(default_factory=list) geometry_is_convex: bool = True geometry_is_closed: bool = True geometry: Optional[Union[Geometry, str]] = '2D' def __contains__(self, point: Point): """Checking :obj:`Domain` contains :obj:`point`. Args: point: checked point Returns: ``True`` if given :obj:`Point` locates in the allowed area borders, otherwise returns ``False`` """ return self.geometry.is_contain_point(self.allowed_area, point) @model_validator(mode='after') def _post_init_validation(self): if self.min_poly_num > self.max_poly_num: raise ValueError('Invalid polygons number interval.') if self.min_points_num > self.max_points_num: raise ValueError('Invalid points number interval.') if self.min_poly_num < 1 or self.max_poly_num < 1: raise ValueError('Number of polygons must be positive value.') min_points_in_poly = 1 + int(self.geometry_is_closed) if self.min_points_num <= min_points_in_poly or self.max_points_num <= min_points_in_poly: raise ValueError('Number of points must be >2/>1 for closed/non closed geometies.') if self.geometry == '2D': self.geometry = Geometry2D( is_closed=self.geometry_is_closed, is_convex=self.geometry_is_convex, ) return self
[docs] @field_validator('min_poly_num') @classmethod def validate_min_poly_num(cls, data: int): """Validates min number of polygons.""" if data < 1: raise ValueError('Min number of polygons must be positive value.') return data
[docs] @field_validator('max_poly_num') @classmethod def validate_max_poly_num(cls, data: int): """Validates max number of polygons.""" if data < 1: raise ValueError('Max number of polygons must be positive value.') return data
[docs] @field_validator('min_points_num') @classmethod def validate_min_points_num(cls, data: int): """Validates min number of points.""" if data < 1: raise ValueError('Max number of polygons must be positive value.') return data
[docs] @field_validator('fixed_points') @classmethod def validate_fixed_points(cls, data: Union[Polygon, list[tuple[float, float]]]): """Validates max number of points.""" if isinstance(data, Polygon): return data return Polygon([Point(*coords) for coords in data])
[docs] @field_validator('prohibited_area') @classmethod def validate_prohibited_area(cls, data: Optional[Union[Structure, str]]): """Validates prohibit area format.""" if isinstance(data, Structure): return data if isinstance(data, str): structs_from_file = parse_structs(data) num_records = len(structs_from_file) if num_records != 1: raise ValueError(f'{num_records} structures found in {data} file, expected 1.') else: return structs_from_file[0] raise TypeError(f'Invalid argument {data}.')
[docs] @field_validator('allowed_area') @classmethod def validate_allowed_area(cls, data: Union[Polygon, list[list[float]]]): """Validates allowed area area format.""" if data is None or len(data) <= 2: raise ValueError('Not enough points for allowed_area.') return Polygon([Point(*coords) for coords in data])
@computed_field def dist_between_polygons(self) -> float: """Min distance between polygons instructure.""" return max(self.max_x - self.min_x, self.max_y - self.min_y) / 35 @computed_field def dist_between_points(self) -> float: """Min dstance between neighbours points in polygon.""" return self.dist_between_polygons * 15 * self.polygon_side @computed_field def min_x(self) -> int: """Min x domain coord.""" return min(p.x for p in self.allowed_area) @computed_field def max_x(self) -> int: """Max x domain coord.""" return max(p.x for p in self.allowed_area) @computed_field def min_y(self) -> int: """Min y domain coord.""" return min(p.y for p in self.allowed_area) @computed_field def max_y(self) -> int: """Max y domain coord.""" return max(p.y for p in self.allowed_area) @computed_field def len_x(self) -> int: """Len of x domain side.""" return abs(self.max_x - self.min_x) @computed_field def len_y(self) -> int: """Len of y domain side.""" return abs(self.max_y - self.min_y) @computed_field def bound_poly(self) -> Polygon: """Allowed area bound. Deprecated.""" return self.allowed_area