Skip to content

Commit 7f6e03c

Browse files
committed
feat: add methods to generate polygon, polygon2d and polygon3d
1 parent e1ce912 commit 7f6e03c

File tree

6 files changed

+140
-29
lines changed

6 files changed

+140
-29
lines changed

geojson_faker/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
fake_multi_line_string,
88
fake_multi_point,
99
fake_point,
10+
fake_polygon,
1011
fake_position,
1112
)
1213

@@ -22,4 +23,5 @@
2223
"fake_multi_point",
2324
"fake_line_string",
2425
"fake_multi_line_string",
26+
"fake_polygon",
2527
]

geojson_faker/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class geo_keys(NamedTuple):
1919
multi_line_string = "multi_line_string"
2020
multi_line_string2d = "multi_line_string2d"
2121
multi_line_string3d = "multi_line_string3d"
22+
polygon = "polygon"
23+
polygon2d = "polygon2d"
24+
polygon3d = "polygon3d"
2225

2326

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

geojson_faker/faker.py

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

4-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point
4+
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
55
from geojson_pydantic.types import Position
66

77
from geojson_faker.constants import geo_keys
@@ -10,6 +10,7 @@
1010
fake_multi_line_string,
1111
fake_multi_point,
1212
fake_point,
13+
fake_polygon,
1314
fake_position,
1415
)
1516
from geojson_faker.types import Dimension
@@ -36,6 +37,9 @@ def __init__(self, random_always: bool = True):
3637
geo_keys.multi_line_string: None,
3738
geo_keys.multi_line_string2d: None,
3839
geo_keys.multi_line_string3d: None,
40+
geo_keys.polygon: None,
41+
geo_keys.polygon2d: None,
42+
geo_keys.polygon3d: None,
3943
}
4044

4145
@property
@@ -116,6 +120,18 @@ def multi_line_string3d(self) -> MultiLineString:
116120
dimension=Dimension.three,
117121
)
118122

123+
@property
124+
def polygon(self) -> Polygon:
125+
return self._fake(func=fake_polygon, geo_key=geo_keys.polygon)
126+
127+
@property
128+
def polygon2d(self) -> Polygon:
129+
return self._fake(func=fake_polygon, geo_key=geo_keys.polygon2d, dimension=Dimension.two)
130+
131+
@property
132+
def polygon3d(self) -> Polygon:
133+
return self._fake(func=fake_polygon, geo_key=geo_keys.polygon3d, dimension=Dimension.three)
134+
119135
def _fake(
120136
self,
121137
func: Callable[[Dimension | None], _GeoJsonType],

geojson_faker/generators.py

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

3-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point
3+
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
44
from geojson_pydantic.types import Position, Position2D, Position3D
55

66
from geojson_faker.constants import DIMENSIONS
@@ -11,6 +11,10 @@ def _get_dimension(dimension: Dimension | None = None) -> Dimension:
1111
return dimension or DIMENSIONS[randrange(len(DIMENSIONS))]
1212

1313

14+
def _randintrange(min_value: int, max_value: int) -> range:
15+
return range(0, randint(min_value, max_value))
16+
17+
1418
def fake_longitude() -> float:
1519
return uniform(-180, 180)
1620

@@ -36,34 +40,66 @@ def fake_point(dimension: Dimension | None = None) -> Point:
3640
return Point(type="Point", coordinates=fake_position(dimension=dimension))
3741

3842

39-
def fake_multi_point(dimension: Dimension | None = None, max_length: int = 1000) -> MultiPoint:
43+
def fake_multi_point(dimension: Dimension | None = None, max_coordinates: int = 100) -> MultiPoint:
4044
return MultiPoint(
4145
type="MultiPoint",
42-
coordinates=[fake_position(dimension=dimension) for _ in range(0, randint(1, max_length))],
46+
coordinates=[fake_position(dimension=dimension) for _ in _randintrange(1, max_coordinates)],
4347
)
4448

4549

46-
def fake_line_string(dimension: Dimension | None = None, max_length: int = 1000) -> LineString:
47-
min_length = 2
48-
if max_length < min_length:
49-
max_length = min_length
50+
def fake_line_string(dimension: Dimension | None = None, max_coordinates: int = 100) -> LineString:
51+
min_coordinates = 2
52+
if max_coordinates < min_coordinates:
53+
max_coordinates = min_coordinates
5054
return LineString(
5155
type="LineString",
5256
coordinates=[
53-
fake_position(dimension=dimension) for _ in range(0, randint(min_length, max_length))
57+
fake_position(dimension=dimension)
58+
for _ in _randintrange(min_coordinates, max_coordinates)
5459
],
5560
)
5661

5762

5863
def fake_multi_line_string(
59-
dimension: Dimension | None = None, max_length: int = 1000
64+
dimension: Dimension | None = None,
65+
max_coordinates: int = 100,
66+
max_line_string_coordinates: int = 100,
6067
) -> MultiLineString:
61-
min_length = 2
62-
if max_length < min_length:
63-
max_length = min_length
68+
min_line_string_coordinates = 2
69+
if max_line_string_coordinates < min_line_string_coordinates:
70+
max_line_string_coordinates = min_line_string_coordinates
6471
coordinates = []
65-
for _ in range(0, randint(1, max_length)):
72+
for _ in _randintrange(1, max_coordinates):
6673
coordinates.append(
67-
fake_position(dimension=dimension) for _ in range(0, randint(min_length, max_length))
74+
[
75+
fake_position(dimension=dimension)
76+
for _ in _randintrange(min_line_string_coordinates, max_line_string_coordinates)
77+
]
6878
)
6979
return MultiLineString(type="MultiLineString", coordinates=coordinates)
80+
81+
82+
def fake_polygon(
83+
dimension: Dimension | None = None,
84+
max_coordinates: int = 100,
85+
max_linear_ring_coordinates: int = 100,
86+
) -> Polygon:
87+
min_linear_ring_coordinates = 4
88+
if max_linear_ring_coordinates < min_linear_ring_coordinates:
89+
max_linear_ring_coordinates = min_linear_ring_coordinates
90+
coordinates = []
91+
for _ in _randintrange(1, max_coordinates):
92+
start_coordinates = end_coordinates = fake_position(dimension=dimension)
93+
linear_ring = []
94+
linear_ring.append(start_coordinates)
95+
linear_ring.extend(
96+
[
97+
fake_position(dimension=dimension)
98+
for _ in _randintrange(
99+
min_linear_ring_coordinates - 2, max_linear_ring_coordinates - 2
100+
)
101+
]
102+
)
103+
linear_ring.append(end_coordinates)
104+
coordinates.append(linear_ring)
105+
return Polygon(type="Polygon", coordinates=coordinates)

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
| MultiPoint | done |
1414
| LineString | done |
1515
| MultiLineString | done |
16-
| Polygon | in progress |
16+
| Polygon | done |
1717
| MultiPolygon | in progress |
1818
| GeometryCollection | in progress |
1919
| Feature | in progress |

tests/faker_test.py

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point
1+
from geojson_pydantic.geometries import LineString, MultiLineString, MultiPoint, Point, Polygon
22
from geojson_pydantic.types import Position, Position2D, Position3D
33

44
from geojson_faker import GeoJsonFaker
@@ -101,7 +101,7 @@ def test_multi_point():
101101

102102
assert isinstance(multi_point, MultiPoint)
103103
assert multi_point.type == "MultiPoint"
104-
assert 0 < len(multi_point.coordinates) < 1000
104+
assert 0 < len(multi_point.coordinates) <= 100
105105

106106
for coordinates in multi_point.coordinates:
107107
assert isinstance(coordinates, Position2D) or isinstance(coordinates, Position3D)
@@ -117,7 +117,7 @@ def test_multi_point2d():
117117

118118
assert isinstance(multi_point, MultiPoint)
119119
assert multi_point.type == "MultiPoint"
120-
assert 0 < len(multi_point.coordinates) < 1000
120+
assert 0 < len(multi_point.coordinates) <= 100
121121

122122
for coordinates in multi_point.coordinates:
123123
assert isinstance(coordinates, Position2D) and not isinstance(coordinates, Position3D)
@@ -131,7 +131,7 @@ def test_multi_point3d():
131131

132132
assert isinstance(multi_point, MultiPoint)
133133
assert multi_point.type == "MultiPoint"
134-
assert 0 < len(multi_point.coordinates) < 1000
134+
assert 0 < len(multi_point.coordinates) <= 100
135135

136136
for coordinates in multi_point.coordinates:
137137
assert isinstance(coordinates, Position3D) and not isinstance(coordinates, Position2D)
@@ -146,7 +146,7 @@ def test_line_string():
146146

147147
assert isinstance(line_string, LineString)
148148
assert line_string.type == "LineString"
149-
assert 2 < len(line_string.coordinates) < 1000
149+
assert 2 <= len(line_string.coordinates) <= 100
150150

151151
for coordinates in line_string.coordinates:
152152
assert isinstance(coordinates, Position2D) or isinstance(coordinates, Position3D)
@@ -162,7 +162,7 @@ def test_line_string2d():
162162

163163
assert isinstance(line_string, LineString)
164164
assert line_string.type == "LineString"
165-
assert 2 < len(line_string.coordinates) < 1000
165+
assert 2 <= len(line_string.coordinates) <= 100
166166

167167
for coordinates in line_string.coordinates:
168168
assert isinstance(coordinates, Position2D) and not isinstance(coordinates, Position3D)
@@ -176,7 +176,7 @@ def test_line_string3d():
176176

177177
assert isinstance(line_string, LineString)
178178
assert line_string.type == "LineString"
179-
assert 2 < len(line_string.coordinates) < 1000
179+
assert 2 <= len(line_string.coordinates) <= 100
180180

181181
for coordinates in line_string.coordinates:
182182
assert isinstance(coordinates, Position3D) and not isinstance(coordinates, Position2D)
@@ -191,11 +191,11 @@ def test_multi_line_string():
191191

192192
assert isinstance(multi_line_string, MultiLineString)
193193
assert multi_line_string.type == "MultiLineString"
194-
assert 0 < len(multi_line_string.coordinates) < 1000
194+
assert 0 < len(multi_line_string.coordinates) <= 100
195195

196196
for line_string in multi_line_string.coordinates:
197197
assert isinstance(line_string, list)
198-
assert 2 < len(multi_line_string.coordinates) < 1000
198+
assert 2 <= len(line_string) <= 100
199199
for coordinates in line_string:
200200
assert isinstance(coordinates, Position2D) or isinstance(coordinates, Position3D)
201201
assert isinstance(coordinates.longitude, float)
@@ -210,11 +210,11 @@ def test_multi_line_string2d():
210210

211211
assert isinstance(multi_line_string, MultiLineString)
212212
assert multi_line_string.type == "MultiLineString"
213-
assert 0 < len(multi_line_string.coordinates) < 1000
213+
assert 0 < len(multi_line_string.coordinates) <= 100
214214

215215
for line_string in multi_line_string.coordinates:
216216
assert isinstance(line_string, list)
217-
assert 2 < len(multi_line_string.coordinates) < 1000
217+
assert 2 <= len(line_string) <= 100
218218
for coordinates in line_string:
219219
assert isinstance(coordinates, Position2D) and not isinstance(coordinates, Position3D)
220220
assert isinstance(coordinates.longitude, float)
@@ -227,13 +227,67 @@ def test_multi_line_string3d():
227227

228228
assert isinstance(multi_line_string, MultiLineString)
229229
assert multi_line_string.type == "MultiLineString"
230-
assert 0 < len(multi_line_string.coordinates) < 1000
230+
assert 0 < len(multi_line_string.coordinates) <= 100
231231

232232
for line_string in multi_line_string.coordinates:
233233
assert isinstance(line_string, list)
234-
assert 2 < len(multi_line_string.coordinates) < 1000
234+
assert 2 <= len(line_string) <= 100
235235
for coordinates in line_string:
236236
assert isinstance(coordinates, Position3D) and not isinstance(coordinates, Position2D)
237237
assert isinstance(coordinates.longitude, float)
238238
assert isinstance(coordinates.latitude, float)
239239
assert isinstance(coordinates.altitude, float)
240+
241+
242+
def test_polygon():
243+
geojson_faker = GeoJsonFaker()
244+
polygon = geojson_faker.polygon
245+
246+
assert isinstance(polygon, Polygon)
247+
assert polygon.type == "Polygon"
248+
assert 0 < len(polygon.coordinates) <= 100
249+
250+
for linear_ring in polygon.coordinates:
251+
assert isinstance(linear_ring, list)
252+
assert 4 <= len(linear_ring) <= 100
253+
for coordinates in linear_ring:
254+
assert isinstance(coordinates, Position2D) or isinstance(coordinates, Position3D)
255+
assert isinstance(coordinates.longitude, float)
256+
assert isinstance(coordinates.latitude, float)
257+
if isinstance(coordinates, Position3D):
258+
assert isinstance(coordinates.altitude, float)
259+
260+
261+
def test_polygon2d():
262+
geojson_faker = GeoJsonFaker()
263+
polygon = geojson_faker.polygon2d
264+
265+
assert isinstance(polygon, Polygon)
266+
assert polygon.type == "Polygon"
267+
assert 0 < len(polygon.coordinates) <= 100
268+
269+
for linear_ring in polygon.coordinates:
270+
assert isinstance(linear_ring, list)
271+
assert 4 <= len(linear_ring) <= 100
272+
for coordinates in linear_ring:
273+
assert isinstance(coordinates, Position2D) and not isinstance(coordinates, Position3D)
274+
assert isinstance(coordinates.longitude, float)
275+
assert isinstance(coordinates.latitude, float)
276+
277+
278+
def test_polygon3d():
279+
geojson_faker = GeoJsonFaker()
280+
polygon = geojson_faker.polygon3d
281+
282+
assert isinstance(polygon, Polygon)
283+
assert polygon.type == "Polygon"
284+
assert 0 < len(polygon.coordinates) <= 100
285+
286+
for linear_ring in polygon.coordinates:
287+
assert isinstance(linear_ring, list)
288+
assert 4 <= len(linear_ring) <= 100
289+
for coordinates in linear_ring:
290+
assert isinstance(coordinates, Position3D) and not isinstance(coordinates, Position2D)
291+
assert isinstance(coordinates.longitude, float)
292+
assert isinstance(coordinates.latitude, float)
293+
assert isinstance(coordinates.altitude, float)

0 commit comments

Comments
 (0)