Skip to content

Commit

Permalink
fix parallel execution, fix modules compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
MangaBoba committed Sep 15, 2023
1 parent 6032236 commit c2f9cb0
Show file tree
Hide file tree
Showing 18 changed files with 414 additions and 444 deletions.
14 changes: 7 additions & 7 deletions gefest/core/geometry/datastructs/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@


class PolyID(Enum):
TEMP = "tmp"
CONSTR = "constraint"
FIXED_AREA = "fixed_area"
FIXED_POLY = "fixed_poly"
PROH_AREA = "prohibited_area"
PROH_TARG = "prohibited_target"
PROH_POLY = "prohibited_poly"
TEMP = 'tmp'
CONSTR = 'constraint'
FIXED_AREA = 'fixed_area'
FIXED_POLY = 'fixed_poly'
PROH_AREA = 'prohibited_area'
PROH_TARG = 'prohibited_target'
PROH_POLY = 'prohibited_poly'


@dataclass
Expand Down
30 changes: 20 additions & 10 deletions gefest/core/geometry/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Optional, Union

import yaml
from pydantic import Field, computed_field, field_validator, model_validator
from pydantic import Field, computed_field, field_validator
from pydantic.dataclasses import dataclass
from pydantic_yaml import parse_yaml_raw_as

Expand All @@ -13,12 +13,14 @@
@dataclass
class Domain:
allowed_area: Union[Polygon, list[list[float]]]
name: str = "main"
name: str = 'main'
min_poly_num: int = 2
max_poly_num: int = 4
min_points_num: int = 20
max_points_num: int = 50
prohibited_area: Optional[Structure] = None
polygon_side: int = 0.05
min_dist_from_boundary: float = 1.0
prohibited_area: Optional[Structure] = Field(default=Structure([]))
fixed_points: Optional[Union[Polygon, list[list[float]]]] = Field(default_factory=list)
geometry: Optional[Geometry2D] = Geometry2D()

Expand All @@ -27,7 +29,7 @@ def parse_raw(self, cfg_file: Path):
with open(cfg_file) as f:
cfg = yaml.safe_load(f)

if "domain" not in cfg:
if 'domain' not in cfg:
raise AttributeError("No 'domain' section {cfg_file} config file.")

return parse_yaml_raw_as(Domain, yaml.dump(cfg['domain']))
Expand All @@ -44,22 +46,30 @@ def __contains__(self, point: Point):

def __post_init__(self):
if self.min_poly_num > self.max_poly_num:
raise ValueError("Invalid points number interval.")
raise ValueError('Invalid points number interval.')
if self.min_points_num > self.max_points_num:
raise ValueError("Invalid points number interval.")
raise ValueError('Invalid points number interval.')

@field_validator("fixed_points")
@field_validator('fixed_points')
def parse_allowed_area(cls, data: Union[Polygon, list[list[float]]]):
if isinstance(data, Polygon):
return data
return Polygon([Point(*coords) for coords in data])

@field_validator("allowed_area")
@field_validator('allowed_area')
def parse_allowed_area(cls, data: Union[Polygon, list[list[float]]]):
if data is None or len(data) <= 2:
raise ValueError("Not enough points for allowed_area.")
raise ValueError('Not enough points for allowed_area.')
return Polygon([Point(*coords) for coords in data])

@computed_field
def dist_between_polygons(self) -> float:
return max(self.max_x - self.min_x, self.max_y - self.min_y) / 35

@computed_field
def dist_between_points(self) -> float:
return self.dist_between_polygons * 15 * self.polygon_side

@computed_field
def min_x(self) -> int:
return min(p.x for p in self.allowed_area)
Expand All @@ -86,4 +96,4 @@ def len_y(self) -> int:

@computed_field
def bound_poly(self) -> Polygon:
return self.allowed_area
return self.allowed_area
2 changes: 1 addition & 1 deletion gefest/core/geometry/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def get_square(self, polygon: Polygon):
pass

@abstractmethod
def is_contain_point(self, poly: Polygon, point: "Point"):
def is_contain_point(self, poly: Polygon, point: Point):
pass

@abstractmethod
Expand Down
37 changes: 35 additions & 2 deletions gefest/core/geometry/geometry_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import numpy as np
from pydantic import BaseModel
from pydantic.dataclasses import dataclass
from shapely import affinity
from shapely import affinity, get_parts
from shapely.affinity import scale
from shapely.geometry import LineString, MultiLineString
from shapely.geometry import Point as GeomPoint
from shapely.geometry import Polygon as GeomPolygon
from shapely.ops import nearest_points
from shapely.geometry import mapping
from shapely.ops import nearest_points, split

from gefest.core.geometry import Point, Polygon, Structure

Expand All @@ -23,6 +25,7 @@ class Geometry2D(Geometry):
(first Point is equal to the last one), otherwise ``False``.
Default value is ``True``
"""

is_closed: bool = True

def get_length(self, polygon: Polygon):
Expand Down Expand Up @@ -94,6 +97,19 @@ def resize_poly(

return rescaled_poly

def rotate_point(
self,
point: Point,
origin: Point,
angle: float,
) -> Polygon:
rotated = affinity.rotate(
GeomPoint(point.x, point.y),
angle,
GeomPoint(origin.x, origin.y),
)
return Point(rotated.x, rotated.y)

def rotate_poly(
self,
poly: Polygon,
Expand Down Expand Up @@ -264,6 +280,23 @@ def _pt_to_geom(self, pt: Point) -> GeomPoint:
"""
return GeomPoint(pt.x, pt.y)

def split_polygon(self, poly, line: tuple[Point, Point], scale_factor=1000):
poly = GeomPolygon([(p.x, p.y) for p in poly])
line = LineString(
[
(line[0].x, line[0].y),
(line[1].x, line[1].y),
],
)
line = scale(
line,
scale_factor,
scale_factor,
)
parts = get_parts(split(poly, line)).tolist()
parts = list(map(lambda p: list(mapping(p)['coordinates'][0][:-1]), parts))
return parts

def min_distance(self, obj_1, obj_2) -> float:
"""Smallest distance between two objects
Args:
Expand Down
58 changes: 41 additions & 17 deletions gefest/core/geometry/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
from typing import Optional

import numpy as np
from loguru import logger

from gefest.core.geometry import Point, Polygon, Structure
from gefest.core.geometry.geometry_2d import Geometry2D

from .domain import Domain


def get_random_structure(domain: Domain) -> Structure:
def get_random_structure(domain: Domain, **kwargs) -> Structure:
# Creating structure with random number of polygons

structure = Structure(polygons=[])
Expand All @@ -24,10 +25,6 @@ def get_random_structure(domain: Domain) -> Structure:
structure.polygons.append(polygon)
else:
continue

for poly in structure:
print(poly[0], poly[-1])

return structure


Expand Down Expand Up @@ -82,21 +79,45 @@ def get_random_point(polygon: Polygon, structure: Structure, domain: Domain) ->
def create_poly(centroid: Point, sigma: int, domain: Domain, geometry: Geometry2D) -> Polygon:
# Creating polygon in the neighborhood of the centroid
# sigma defines neighborhood

num_points = randint(
domain.min_points_num, domain.max_points_num,
domain.min_points_num,
domain.max_points_num,
) # Number of points in a polygon
points = []
for _ in range(num_points):
point = create_polygon_point(centroid, sigma) # point in polygon
while not in_bound(point, domain): # checking if a point is in domain
cntr = 0
while len(points) < num_points:
cntr += 1

point = create_polygon_point(centroid, sigma)
while not in_bound(point, domain):
point = create_polygon_point(centroid, sigma)
points.append(point)
if domain.geometry.is_closed:
points.append(points[0])

poly = geometry.get_convex(Polygon(points=points)) # avoid self intersection in polygon

ind = len(points) - 1
if ind > 0:
if (
np.linalg.norm(
np.array(points[ind].coords[:2]) - np.array(points[ind - 1].coords[:2]), ord=1
)
< domain.dist_between_points
):
del points[ind]
if len(points) == num_points:
if (
np.linalg.norm(
np.array(points[-1].coords[:2]) - np.array(points[0].coords[:2]), ord=1
)
< domain.dist_between_points
):
del points[-1]
if len(points) == num_points:
if domain.geometry.is_closed:
points.append(points[0])
poly = geometry.get_convex(Polygon(points=points))
points = poly.points
if cntr > 100 and len(points) > 4:
break

# logger.info(f'Create poly finish, {cntr} iterations.')
return poly


Expand All @@ -117,7 +138,9 @@ def create_area(domain: Domain, structure: Structure, geometry: Geometry2D) -> (
"""
centroid = create_random_point(domain)
min_dist = distance(
centroid, structure, geometry,
centroid,
structure,
geometry,
) # Distance to the nearest polygon in the structure
max_attempts = 20
while min_dist < 2.5 * sigma:
Expand Down Expand Up @@ -149,7 +172,8 @@ def create_random_point(domain: Domain) -> Point:
def create_polygon_point(centroid: Point, sigma: int) -> Point:
# Creating polygon point inside the neighborhood defined by the centroid
point = Point(
np.random.normal(centroid.x, sigma, 1)[0], np.random.normal(centroid.y, sigma, 1)[0],
np.random.normal(centroid.x, sigma, 1)[0],
np.random.normal(centroid.y, sigma, 1)[0],
)

return point
Expand Down
10 changes: 6 additions & 4 deletions gefest/core/opt/adapters/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def __init__(self):
def _point_to_node(self, point):
# Prepare content for nodes
if isinstance(point, OptNode):
self._log.warn("Unexpected: OptNode found in adapter instead" "Point.")
self._log.warn('Unexpected: OptNode found in adapter instead' 'Point.')
else:
content = {"name": f"pt_{point.x}_{point.y}", "params": {}}
content = {'name': f'pt_{point.x}_{point.y}', 'params': {}}
node = OptNode(content=content)
node.content["params"] = {"x": point.x, "y": point.y}
node.content['params'] = {'x': point.x, 'y': point.y}
return node

def _adapt(self, adaptee: Structure):
Expand All @@ -39,7 +39,9 @@ def _adapt(self, adaptee: Structure):
return graph

def _restore(
self, opt_graph: OptGraph, metadata: Optional[Dict[str, Any]] = None,
self,
opt_graph: OptGraph,
metadata: Optional[Dict[str, Any]] = None,
) -> Structure:
"""Convert OptGraph class into Structure class"""
structure = []
Expand Down
83 changes: 0 additions & 83 deletions gefest/core/opt/gen_design.py

This file was deleted.

Loading

0 comments on commit c2f9cb0

Please sign in to comment.