togo 0.1.3__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of togo might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: togo
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Lightweight Python bindings for the TG geometry library
5
5
  Author-email: Giorgio Salluzzo <giorgio.salluzzo@gmail.com>
6
6
  License: MIT
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "togo"
11
- version = "0.1.3"
11
+ version = "0.1.4"
12
12
  description = "Lightweight Python bindings for the TG geometry library"
13
13
  readme = "README.md"
14
14
  authors = [
@@ -33,3 +33,6 @@ Tracker = "https://github.com/mindflayer/togo/issues"
33
33
  addopts = "-v -x -q"
34
34
  testpaths = ["tests"]
35
35
  pythonpath = ["."]
36
+
37
+ [tool.cython-lint]
38
+ max-line-length = 100
togo-0.1.4/setup.py ADDED
@@ -0,0 +1,65 @@
1
+ import os
2
+ import urllib.request
3
+ from urllib.parse import urlparse
4
+
5
+ from setuptools import setup, Extension
6
+ from Cython.Build import cythonize
7
+
8
+
9
+ # Download the tg and tgx source and header files if not already present
10
+ NEEDED_FILES = [
11
+ "https://raw.githubusercontent.com/tidwall/tg/main/tg.c",
12
+ "https://raw.githubusercontent.com/tidwall/tg/main/tg.h",
13
+ "https://raw.githubusercontent.com/tidwall/tgx/main/tgx.c",
14
+ "https://raw.githubusercontent.com/tidwall/tgx/main/tgx.h",
15
+ ]
16
+
17
+
18
+ def download_if_missing(url: str, filename: str):
19
+ if not os.path.exists(filename):
20
+ print(f"Downloading {filename}...")
21
+ urllib.request.urlretrieve(url, filename)
22
+
23
+
24
+ for url in NEEDED_FILES:
25
+ filename = os.path.basename(urlparse(url).path)
26
+ download_if_missing(url, filename)
27
+
28
+ # Enable optional AddressSanitizer build via env var ASAN=1
29
+ asan_enabled = os.environ.get("ASAN") == "1"
30
+ extra_compile_args = []
31
+ extra_link_args = []
32
+ if asan_enabled:
33
+ # Favor debuggability over speed
34
+ extra_compile_args += [
35
+ "-O1",
36
+ "-g",
37
+ "-fno-omit-frame-pointer",
38
+ "-fsanitize=address",
39
+ ]
40
+ extra_link_args += [
41
+ "-fsanitize=address",
42
+ ]
43
+
44
+ setup(
45
+ ext_modules=cythonize(
46
+ [
47
+ Extension(
48
+ "togo",
49
+ sources=["togo.pyx", "tg.c", "tgx.c"],
50
+ include_dirs=[
51
+ ".",
52
+ "/usr/include",
53
+ "/usr/include/geos",
54
+ ], # Add GEOS include path
55
+ libraries=["geos_c"], # Link against libgeos_c
56
+ extra_compile_args=extra_compile_args,
57
+ extra_link_args=extra_link_args,
58
+ )
59
+ ]
60
+ ),
61
+ # Explicitly disable auto-discovery in flat layout
62
+ packages=[],
63
+ py_modules=[],
64
+ license="MIT",
65
+ )
@@ -58,3 +58,34 @@ def test_buenos_aires():
58
58
  b_aires_center = rect.center()
59
59
  assert b_aires_center.as_tuple() == (-58.38268310487112, -34.70305640194427)
60
60
  assert b_aires.intersects(b_aires_center.as_geometry())
61
+
62
+
63
+ def test_togo_union_benin():
64
+ g = Geometry.unary_union(
65
+ [Geometry(TOGO, fmt="geojson"), Geometry(BENIN, fmt="geojson")]
66
+ )
67
+ # The union should not be empty and should be a valid geometry
68
+ assert not g.is_empty()
69
+ assert g.type_string() == "Polygon"
70
+ wkt = g.to_wkt()
71
+ new_g = Geometry(wkt, fmt="wkt")
72
+ assert new_g.equals(g)
73
+ assert new_g.rect() == g.rect()
74
+ assert new_g.within(g) and g.within(new_g)
75
+ assert g.contains(new_g) and new_g.contains(g)
76
+ assert g.intersects(new_g) and new_g.intersects(g)
77
+ assert not g.disjoint(new_g) and not new_g.disjoint(g)
78
+ assert not g.touches(new_g) and not new_g.touches(g)
79
+ assert g.num_points() == new_g.num_points()
80
+ assert g.dims() == new_g.dims()
81
+ assert g.has_z() == new_g.has_z()
82
+ assert g.has_m() == new_g.has_m()
83
+ assert g.is_feature() == new_g.is_feature()
84
+ assert g.is_featurecollection() == new_g.is_featurecollection()
85
+ assert g.to_geojson() == new_g.to_geojson()
86
+ assert g.to_hex() == new_g.to_hex()
87
+ assert g.to_wkb() == new_g.to_wkb()
88
+ assert g.to_geobin() == new_g.to_geobin()
89
+ assert g.memsize() == new_g.memsize()
90
+ assert g.coveredby(new_g) and new_g.coveredby(g)
91
+ assert g.covers(new_g) and new_g.covers(g)
@@ -1,5 +1,5 @@
1
1
  import pytest
2
- from togo import Geometry
2
+ from togo import Geometry, Point, Ring, Poly
3
3
 
4
4
 
5
5
  def test_geometry_wkt():
@@ -193,3 +193,43 @@ def test_geometry_geom_at():
193
193
  assert g1.type_string() == "Point"
194
194
  assert g0.point().x == 1.0 and g0.point().y == 2.0
195
195
  assert g1.point().x == 3.0 and g1.point().y == 4.0
196
+
197
+
198
+ def test_tgx_meters_grid():
199
+ # Create a simple point geometry
200
+ g = Geometry('{"type": "Point", "coordinates": [1.0, 2.0]}')
201
+ origin = Point(0.0, 0.0)
202
+ g2 = g.to_meters_grid(origin)
203
+ g3 = g2.from_meters_grid(origin)
204
+ # Should round-trip back to original coordinates
205
+ assert g3.point().x == pytest.approx(1.0, abs=1e-6)
206
+ assert g3.point().y == pytest.approx(2.0, abs=1e-6)
207
+
208
+
209
+ def test_unary_union_geos_lines():
210
+ g1 = Geometry("LINESTRING(0 0, 1 1)", fmt="wkt")
211
+ g2 = Geometry("LINESTRING(1 1, 2 2)", fmt="wkt")
212
+ u = Geometry.unary_union([g1, g2])
213
+ assert u.type_string() == "MultiLineString"
214
+ wkt = u.to_wkt()
215
+ assert wkt == "MULTILINESTRING((0 0,1 1),(1 1,2 2))"
216
+
217
+
218
+ def test_unary_union_geos_polys():
219
+ # Two intersecting squares
220
+ outer1 = Ring([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
221
+ poly1 = Poly(outer1)
222
+ outer2 = Ring([(1, 1), (3, 1), (3, 3), (1, 3), (1, 1)])
223
+ poly2 = Poly(outer2)
224
+ union_geom = Geometry.unary_union([poly1, poly2])
225
+ # Should be a single Polygon
226
+ assert union_geom.type_string() == "Polygon"
227
+ # Area should be 7 (each square is 4, overlap is 1)
228
+ # So union area = 4 + 4 - 1 = 7
229
+ area = union_geom.poly().exterior().area()
230
+ assert area == 7.0
231
+ # Bounding box should be ((0,0),(3,3))
232
+ assert union_geom.rect() == ((0.0, 0.0), (3.0, 3.0))
233
+ # WKT should represent the merged polygon
234
+ wkt = union_geom.to_wkt()
235
+ assert wkt == "POLYGON((2 0,0 0,0 2,1 2,1 3,3 3,3 1,2 1,2 0))"