|
14 | 14 | # KIND, either express or implied. See the License for the |
15 | 15 | # specific language governing permissions and limitations |
16 | 16 | # under the License. |
17 | | -import os |
18 | 17 | import math |
| 18 | +import os |
19 | 19 | import warnings |
20 | 20 | from pathlib import Path |
21 | | -from typing import TYPE_CHECKING, List, Tuple |
| 21 | +from typing import TYPE_CHECKING, Iterable, List, Literal, Optional, Tuple, Union |
22 | 22 |
|
23 | 23 | import geoarrow.pyarrow as ga |
24 | 24 | import pyarrow as pa |
|
29 | 29 | import sedonadb |
30 | 30 |
|
31 | 31 |
|
| 32 | +def random_geometry( |
| 33 | + n: int = 1024, |
| 34 | + geometry_type: Literal[ |
| 35 | + "Point", |
| 36 | + "LineString", |
| 37 | + "Polygon", |
| 38 | + "MultiPoint", |
| 39 | + "MultiLineString", |
| 40 | + "MultiPolygon", |
| 41 | + "GeometryCollection", |
| 42 | + ] = "Point", |
| 43 | + *, |
| 44 | + num_vertices: Union[int, Tuple[int, int]] = 4, |
| 45 | + num_parts: Union[int, Tuple[int, int]] = (1, 3), |
| 46 | + size: Union[float, Tuple[float, float]] = (5.0, 20.0), |
| 47 | + bounds: Iterable[float] = (-170, -80, 170, 80), |
| 48 | + hole_rate: float = 0.0, |
| 49 | + empty_rate: float = 0.0, |
| 50 | + null_rate: float = 0.0, |
| 51 | + seed: Optional[int] = None, |
| 52 | +) -> "sedonadb.dataframe.DataFrame": |
| 53 | + import json |
| 54 | + import time |
| 55 | + |
| 56 | + import sedonadb |
| 57 | + |
| 58 | + if isinstance(num_vertices, tuple): |
| 59 | + num_vertices_min, num_vertices_max = num_vertices |
| 60 | + else: |
| 61 | + num_vertices_min = num_vertices_max = num_vertices |
| 62 | + |
| 63 | + if isinstance(num_parts, tuple): |
| 64 | + num_parts_min, num_parts_max = num_parts |
| 65 | + else: |
| 66 | + num_parts_min = num_parts_max = num_parts |
| 67 | + |
| 68 | + if isinstance(size, tuple): |
| 69 | + size_min, size_max = size |
| 70 | + else: |
| 71 | + size_min = size |
| 72 | + size_max = size + size / 1e3 |
| 73 | + |
| 74 | + if num_vertices_min > num_vertices_max: |
| 75 | + raise ValueError("num_vertices_min > num_vertices_max") |
| 76 | + if num_parts_min > num_parts_max: |
| 77 | + raise ValueError("num_parts_min > num_parts_max") |
| 78 | + if size_min > size_max: |
| 79 | + raise ValueError("size_min > size_max") |
| 80 | + |
| 81 | + bounds = [float(b) for b in bounds] |
| 82 | + if len(bounds) != 4: |
| 83 | + raise ValueError( |
| 84 | + f"Expected bounds as [xmin, ymin, xmax, ymax] but got {bounds}" |
| 85 | + ) |
| 86 | + |
| 87 | + width = bounds[2] - bounds[0] |
| 88 | + height = bounds[3] - bounds[1] |
| 89 | + if size_min > width or size_min > height: |
| 90 | + raise ValueError("size > height / 2 or width / 2 of bounds") |
| 91 | + |
| 92 | + args = { |
| 93 | + "bounds": bounds, |
| 94 | + "empty_rate": max(min(empty_rate, 1.0), 0.0), |
| 95 | + "geom_type": geometry_type, |
| 96 | + "null_rate": max(min(null_rate, 1.0), 0.0), |
| 97 | + "num_parts_range": [num_parts_min, num_parts_max], |
| 98 | + "polygon_hole_rate": max(min(hole_rate, 1.0), 0.0), |
| 99 | + "seed": int(seed) if seed is not None else round(time.time() * 1000), |
| 100 | + "size_range": [size_min, size_max], |
| 101 | + "target_rows": int(n), |
| 102 | + "vertices_per_linestring_range": [num_vertices_min, num_vertices_max], |
| 103 | + } |
| 104 | + |
| 105 | + sd = sedonadb.connect() |
| 106 | + return sd.sql( |
| 107 | + f"SELECT id, geometry FROM sd_random_geometry('{json.dumps(args)}')" |
| 108 | + ).limit(int(n)) |
| 109 | + |
| 110 | + |
32 | 111 | def skip_if_not_exists(path: Path): |
33 | 112 | """Skip a test using pytest.skip() if path does not exist |
34 | 113 |
|
|
0 commit comments