Skip to content

Commit 33d1fb9

Browse files
committed
feat: add methods to generate multi_polygon, multi_polygon2d and multi_polygon3d
1 parent 7f6e03c commit 33d1fb9

File tree

5 files changed

+142
-4
lines changed

5 files changed

+142
-4
lines changed

geojson_faker/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ class geo_keys(NamedTuple):
2222
polygon = "polygon"
2323
polygon2d = "polygon2d"
2424
polygon3d = "polygon3d"
25+
multi_polygon = "multi_polygon"
26+
multi_polygon2d = "multi_polygon2d"
27+
multi_polygon3d = "multi_polygon3d"
2528

2629

2730
DIMENSIONS = [Dimension.two, Dimension.three]

geojson_faker/faker.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
from collections.abc import Callable
22
from typing import TypeVar
33

4-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
4+
from geojson_pydantic.geometries import (
5+
LineString,
6+
MultiLineString,
7+
MultiPoint,
8+
MultiPolygon,
9+
Point,
10+
Polygon,
11+
)
512
from geojson_pydantic.types import Position
613

714
from geojson_faker.constants import geo_keys
815
from geojson_faker.generators import (
916
fake_line_string,
1017
fake_multi_line_string,
1118
fake_multi_point,
19+
fake_multi_polygon,
1220
fake_point,
1321
fake_polygon,
1422
fake_position,
@@ -40,6 +48,9 @@ def __init__(self, random_always: bool = True):
4048
geo_keys.polygon: None,
4149
geo_keys.polygon2d: None,
4250
geo_keys.polygon3d: None,
51+
geo_keys.multi_polygon: None,
52+
geo_keys.multi_polygon2d: None,
53+
geo_keys.multi_polygon3d: None,
4354
}
4455

4556
@property
@@ -132,6 +143,22 @@ def polygon2d(self) -> Polygon:
132143
def polygon3d(self) -> Polygon:
133144
return self._fake(func=fake_polygon, geo_key=geo_keys.polygon3d, dimension=Dimension.three)
134145

146+
@property
147+
def multi_polygon(self) -> MultiPolygon:
148+
return self._fake(func=fake_multi_polygon, geo_key=geo_keys.multi_polygon)
149+
150+
@property
151+
def multi_polygon2d(self) -> MultiPolygon:
152+
return self._fake(
153+
func=fake_multi_polygon, geo_key=geo_keys.multi_polygon2d, dimension=Dimension.two
154+
)
155+
156+
@property
157+
def multi_polygon3d(self) -> MultiPolygon:
158+
return self._fake(
159+
func=fake_multi_polygon, geo_key=geo_keys.multi_polygon3d, dimension=Dimension.three
160+
)
161+
135162
def _fake(
136163
self,
137164
func: Callable[[Dimension | None], _GeoJsonType],

geojson_faker/generators.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
from random import randint, randrange, uniform
22

3-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
3+
from geojson_pydantic.geometries import (
4+
LineString,
5+
MultiLineString,
6+
MultiPoint,
7+
MultiPolygon,
8+
Point,
9+
Polygon,
10+
)
411
from geojson_pydantic.types import Position, Position2D, Position3D
512

613
from geojson_faker.constants import DIMENSIONS
@@ -103,3 +110,33 @@ def fake_polygon(
103110
linear_ring.append(end_coordinates)
104111
coordinates.append(linear_ring)
105112
return Polygon(type="Polygon", coordinates=coordinates)
113+
114+
115+
def fake_multi_polygon(
116+
dimension: Dimension | None = None,
117+
max_coordinates: int = 100,
118+
max_polygon_coordinates: int = 100,
119+
max_linear_ring_coordinates: int = 100,
120+
) -> MultiPolygon:
121+
min_linear_ring_coordinates = 4
122+
if max_linear_ring_coordinates < min_linear_ring_coordinates:
123+
max_linear_ring_coordinates = min_linear_ring_coordinates
124+
coordinates = []
125+
for _ in _randintrange(1, max_coordinates):
126+
polygon_coordinates = []
127+
for _ in _randintrange(1, max_polygon_coordinates):
128+
start_coordinates = end_coordinates = fake_position(dimension=dimension)
129+
linear_ring = []
130+
linear_ring.append(start_coordinates)
131+
linear_ring.extend(
132+
[
133+
fake_position(dimension=dimension)
134+
for _ in _randintrange(
135+
min_linear_ring_coordinates - 2, max_linear_ring_coordinates - 2
136+
)
137+
]
138+
)
139+
linear_ring.append(end_coordinates)
140+
polygon_coordinates.append(linear_ring)
141+
coordinates.append(polygon_coordinates)
142+
return MultiPolygon(type="MultiPolygon", coordinates=coordinates)

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
| LineString | done |
1515
| MultiLineString | done |
1616
| Polygon | done |
17-
| MultiPolygon | in progress |
17+
| MultiPolygon | done |
1818
| GeometryCollection | in progress |
1919
| Feature | in progress |
2020
| FeatureCollection | in progress |

tests/faker_test.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
1+
from geojson_pydantic.geometries import (
2+
LineString,
3+
MultiLineString,
4+
MultiPoint,
5+
MultiPolygon,
6+
Point,
7+
Polygon,
8+
)
29
from geojson_pydantic.types import Position, Position2D, Position3D
310

411
from geojson_faker import GeoJsonFaker
@@ -291,3 +298,67 @@ def test_polygon3d():
291298
assert isinstance(coordinates.longitude, float)
292299
assert isinstance(coordinates.latitude, float)
293300
assert isinstance(coordinates.altitude, float)
301+
302+
303+
def test_multi_polygon():
304+
geojson_faker = GeoJsonFaker()
305+
multi_polygon = geojson_faker.multi_polygon
306+
307+
assert isinstance(multi_polygon, MultiPolygon)
308+
assert multi_polygon.type == "MultiPolygon"
309+
assert 0 < len(multi_polygon.coordinates) <= 100
310+
311+
for polygon in multi_polygon.coordinates:
312+
assert isinstance(polygon, list)
313+
for linear_ring in polygon:
314+
assert isinstance(linear_ring, list)
315+
assert 4 <= len(linear_ring) <= 100
316+
for coordinates in linear_ring:
317+
assert isinstance(coordinates, Position2D) or isinstance(coordinates, Position3D)
318+
assert isinstance(coordinates.longitude, float)
319+
assert isinstance(coordinates.latitude, float)
320+
if isinstance(coordinates, Position3D):
321+
assert isinstance(coordinates.altitude, float)
322+
323+
324+
def test_multi_polygon2d():
325+
geojson_faker = GeoJsonFaker()
326+
multi_polygon = geojson_faker.multi_polygon2d
327+
328+
assert isinstance(multi_polygon, MultiPolygon)
329+
assert multi_polygon.type == "MultiPolygon"
330+
assert 0 < len(multi_polygon.coordinates) <= 100
331+
332+
for polygon in multi_polygon.coordinates:
333+
assert isinstance(polygon, list)
334+
for linear_ring in polygon:
335+
assert isinstance(linear_ring, list)
336+
assert 4 <= len(linear_ring) <= 100
337+
for coordinates in linear_ring:
338+
assert isinstance(coordinates, Position2D) and not isinstance(
339+
coordinates, Position3D
340+
)
341+
assert isinstance(coordinates.longitude, float)
342+
assert isinstance(coordinates.latitude, float)
343+
344+
345+
def test_multi_polygon3d():
346+
geojson_faker = GeoJsonFaker()
347+
multi_polygon = geojson_faker.multi_polygon3d
348+
349+
assert isinstance(multi_polygon, MultiPolygon)
350+
assert multi_polygon.type == "MultiPolygon"
351+
assert 0 < len(multi_polygon.coordinates) <= 100
352+
353+
for polygon in multi_polygon.coordinates:
354+
assert isinstance(polygon, list)
355+
for linear_ring in polygon:
356+
assert isinstance(linear_ring, list)
357+
assert 4 <= len(linear_ring) <= 100
358+
for coordinates in linear_ring:
359+
assert isinstance(coordinates, Position3D) and not isinstance(
360+
coordinates, Position2D
361+
)
362+
assert isinstance(coordinates.longitude, float)
363+
assert isinstance(coordinates.latitude, float)
364+
assert isinstance(coordinates.altitude, float)

0 commit comments

Comments
 (0)