togo 0.1.0__tar.gz → 0.1.3__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.

togo-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.4
2
+ Name: togo
3
+ Version: 0.1.3
4
+ Summary: Lightweight Python bindings for the TG geometry library
5
+ Author-email: Giorgio Salluzzo <giorgio.salluzzo@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/mindflayer/togo
8
+ Project-URL: Source, https://github.com/mindflayer/togo
9
+ Project-URL: Tracker, https://github.com/mindflayer/togo/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: C
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Scientific/Engineering :: GIS
15
+ Requires-Python: >=3.8
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: license
19
+ Dynamic: license-file
20
+
21
+ # ToGo
22
+ Python bindings for [TG](https://github.com/tidwall/tg)
23
+ (Geometry library for C - Fast point-in-polygon)
24
+
25
+ ToGo is a high-performance Python library for computational geometry, providing a Cython wrapper around the above-mentioned C library.
26
+
27
+ The main goal is to offer a Pythonic, object-oriented, fast and memory-efficient library for geometric operations, including spatial predicates, format conversions, and spatial indexing.
28
+
29
+ While ToGo's API interfaces are still a work in progress, the underling C library is stable and well-tested.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install togo
35
+ ```
36
+
37
+ ## Features
38
+
39
+ - Fast and efficient geometric operations
40
+ - Support for standard geometry types: Point, Line, Ring, Polygon, and their multi-variants
41
+ - Geometric predicates: contains, intersects, covers, touches, etc.
42
+ - Format conversion between WKT, GeoJSON, WKB, and HEX
43
+ - Spatial indexing for accelerated queries
44
+ - Memory-efficient C implementation with Python-friendly interface
45
+
46
+ ## Basic Usage
47
+
48
+ ```python
49
+ from togo import Geometry, Point, Ring, Poly
50
+
51
+ # Create a geometry from GeoJSON
52
+ geom = Geometry('{"type":"Point","coordinates":[1.0,2.0]}')
53
+
54
+ # Create a point
55
+ point = Point(1.0, 2.0)
56
+
57
+ # Create a polygon
58
+ ring = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
59
+ polygon = Poly(ring)
60
+
61
+ # Convert to various formats
62
+ wkt = polygon.as_geometry().to_wkt()
63
+ geojson = polygon.as_geometry().to_geojson()
64
+
65
+ # Perform spatial predicates
66
+ point_geom = point.as_geometry()
67
+ contains = polygon.as_geometry().contains(point_geom)
68
+ ```
69
+
70
+ ## Core Classes
71
+
72
+ ### Geometry
73
+
74
+ The base class that wraps tg_geom structures and provides core operations:
75
+
76
+ ```python
77
+ # Create from various formats
78
+ g1 = Geometry('POINT(1 2)', fmt='wkt')
79
+ g2 = Geometry('{"type":"Point","coordinates":[1,2]}', fmt='geojson')
80
+
81
+ # Geometric predicates
82
+ g1.intersects(g2)
83
+ g1.contains(g2)
84
+ g1.within(g2)
85
+
86
+ # Format conversion
87
+ g1.to_wkt()
88
+ g1.to_geojson()
89
+
90
+ # Access sub-geometries by index (e.g., for GeometryCollection, MultiPoint, etc.)
91
+ gc = Geometry('GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))', fmt='wkt')
92
+ first = gc[0] # Bound to TG function call tg_geom_geometry_at(idx)
93
+ second = gc[1]
94
+ print(first.type_string()) # 'Point'
95
+ ```
96
+
97
+ ### Point
98
+
99
+ ```python
100
+ from togo import Point
101
+
102
+ # Create a point
103
+ p = Point(1.0, 2.0)
104
+
105
+ # Access coordinates
106
+ print(f"X: {p.x}, Y: {p.y}")
107
+
108
+ # Get as a tuple
109
+ print(p.as_tuple())
110
+
111
+ # Convert to a Geometry object
112
+ geom = p.as_geometry()
113
+ print(geom.type_string())
114
+ ```
115
+
116
+ ### Segment
117
+
118
+ ```python
119
+ from togo import Segment, Point
120
+
121
+ # Create a segment from two points (or tuples)
122
+ seg = Segment(Point(0, 0), Point(1, 1))
123
+ # Or using tuples
124
+ tuple_seg = Segment((0, 0), (1, 1))
125
+
126
+ # Access endpoints
127
+ print(seg.a) # Point(0, 0)
128
+ print(seg.b) # Point(1, 1)
129
+
130
+ # Get the bounding rectangle
131
+ rect = seg.rect()
132
+ print(rect) # ((0.0, 0.0), (1.0, 1.0))
133
+
134
+ # Check intersection with another segment
135
+ other = Segment((1, 1), (2, 2))
136
+ print(seg.intersects(other)) # True or False
137
+ ```
138
+
139
+ ### Line
140
+
141
+ ```python
142
+ from togo import Line
143
+
144
+ # Create a line from a list of tuples
145
+ line = Line([(0,0), (1,1), (2,0)])
146
+
147
+ # Get number of points
148
+ print(f"Number of points: {line.num_points()}")
149
+
150
+ # Get all points as a list of tuples
151
+ print(f"Points: {line.points()}")
152
+
153
+ # Get the length of the line
154
+ print(f"Length: {line.length()}")
155
+
156
+ # Get the bounding box
157
+ print(f"Bounding box: {line.rect()}")
158
+
159
+ # Get a point by index
160
+ print(f"First point: {line[0].as_tuple()}")
161
+ ```
162
+
163
+ ### Ring
164
+
165
+ ```python
166
+ from togo import Ring
167
+
168
+ # Create a ring (must be closed)
169
+ ring = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
170
+
171
+ # Get area and perimeter
172
+ print(f"Area: {ring.area()}")
173
+ print(f"Perimeter: {ring.perimeter()}")
174
+
175
+ # Check if it's convex or clockwise
176
+ print(f"Is convex: {ring.is_convex()}")
177
+ print(f"Is clockwise: {ring.is_clockwise()}")
178
+
179
+ # Get bounding box
180
+ min_pt, max_pt = ring.rect().min, ring.rect().max
181
+ print(f"Bounding box: {min_pt.as_tuple()}, {max_pt.as_tuple()}")
182
+ ```
183
+
184
+ ### Poly
185
+
186
+ ```python
187
+ from togo import Poly, Ring, Point
188
+
189
+ # Create a polygon with one exterior ring and one interior hole
190
+ exterior = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
191
+ hole1 = Ring([(1,1), (2,1), (2,2), (1,2), (1,1)])
192
+ poly = Poly(exterior, holes=[hole1])
193
+
194
+ # Get the exterior ring
195
+ ext_ring = poly.exterior()
196
+ print(f"Exterior has {ext_ring.num_points()} points")
197
+
198
+ # Get number of holes
199
+ print(f"Number of holes: {poly.num_holes()}")
200
+
201
+ # Get a hole by index
202
+ h = poly.hole(0)
203
+ print(f"Hole area: {h.area()}")
204
+
205
+ # A polygon is a geometry, so you can use geometry methods
206
+ geom = poly.as_geometry()
207
+ print(f"Contains point (5,5): {geom.contains(Point(5,5).as_geometry())}")
208
+ # Point is inside the hole, so it is not contained by the polygon
209
+ print(f"Contains point (1.5,1.5): {geom.contains(Point(1.5,1.5).as_geometry())}")
210
+ ```
211
+
212
+ ### MultiGeometries
213
+
214
+ Creating collections of geometries:
215
+
216
+ ```python
217
+ from togo import Geometry, Point, Line, Poly, Ring
218
+
219
+ # Create a MultiPoint
220
+ multi_point = Geometry.from_multipoint([(0,0), (1,1), Point(2,2)])
221
+
222
+ # Create a MultiLineString
223
+ multi_line = Geometry.from_multilinestring([
224
+ [(0,0), (1,1)],
225
+ Line([(2,2), (3,3)])
226
+ ])
227
+
228
+ # Create a MultiPolygon
229
+ poly1 = Poly(Ring([(0,0), (1,0), (1,1), (0,1), (0,0)]))
230
+ poly2 = Poly(Ring([(2,2), (3,2), (3,3), (2,3), (2,2)]))
231
+ multi_poly = Geometry.from_multipolygon([poly1, poly2])
232
+ ```
233
+
234
+ ## Polygon Indexing
235
+
236
+ Togo supports different polygon indexing strategies for optimized spatial operations:
237
+
238
+ ```python
239
+ from togo import TGIndex, set_polygon_indexing_mode
240
+
241
+ # Set the indexing mode
242
+ set_polygon_indexing_mode(TGIndex.NATURAL) # or NONE, YSTRIPES
243
+ ```
244
+
245
+ ## Performance Considerations
246
+
247
+ - Togo is optimized for speed and memory efficiency
248
+ - For large datasets, proper indexing can significantly improve performance
249
+ - Creating geometries with the appropriate format avoids unnecessary conversions
250
+
251
+ Soon there will be a full API documentation, for now please refer to the test suite for more usage examples.
togo-0.1.3/README.md ADDED
@@ -0,0 +1,231 @@
1
+ # ToGo
2
+ Python bindings for [TG](https://github.com/tidwall/tg)
3
+ (Geometry library for C - Fast point-in-polygon)
4
+
5
+ ToGo is a high-performance Python library for computational geometry, providing a Cython wrapper around the above-mentioned C library.
6
+
7
+ The main goal is to offer a Pythonic, object-oriented, fast and memory-efficient library for geometric operations, including spatial predicates, format conversions, and spatial indexing.
8
+
9
+ While ToGo's API interfaces are still a work in progress, the underling C library is stable and well-tested.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install togo
15
+ ```
16
+
17
+ ## Features
18
+
19
+ - Fast and efficient geometric operations
20
+ - Support for standard geometry types: Point, Line, Ring, Polygon, and their multi-variants
21
+ - Geometric predicates: contains, intersects, covers, touches, etc.
22
+ - Format conversion between WKT, GeoJSON, WKB, and HEX
23
+ - Spatial indexing for accelerated queries
24
+ - Memory-efficient C implementation with Python-friendly interface
25
+
26
+ ## Basic Usage
27
+
28
+ ```python
29
+ from togo import Geometry, Point, Ring, Poly
30
+
31
+ # Create a geometry from GeoJSON
32
+ geom = Geometry('{"type":"Point","coordinates":[1.0,2.0]}')
33
+
34
+ # Create a point
35
+ point = Point(1.0, 2.0)
36
+
37
+ # Create a polygon
38
+ ring = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
39
+ polygon = Poly(ring)
40
+
41
+ # Convert to various formats
42
+ wkt = polygon.as_geometry().to_wkt()
43
+ geojson = polygon.as_geometry().to_geojson()
44
+
45
+ # Perform spatial predicates
46
+ point_geom = point.as_geometry()
47
+ contains = polygon.as_geometry().contains(point_geom)
48
+ ```
49
+
50
+ ## Core Classes
51
+
52
+ ### Geometry
53
+
54
+ The base class that wraps tg_geom structures and provides core operations:
55
+
56
+ ```python
57
+ # Create from various formats
58
+ g1 = Geometry('POINT(1 2)', fmt='wkt')
59
+ g2 = Geometry('{"type":"Point","coordinates":[1,2]}', fmt='geojson')
60
+
61
+ # Geometric predicates
62
+ g1.intersects(g2)
63
+ g1.contains(g2)
64
+ g1.within(g2)
65
+
66
+ # Format conversion
67
+ g1.to_wkt()
68
+ g1.to_geojson()
69
+
70
+ # Access sub-geometries by index (e.g., for GeometryCollection, MultiPoint, etc.)
71
+ gc = Geometry('GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))', fmt='wkt')
72
+ first = gc[0] # Bound to TG function call tg_geom_geometry_at(idx)
73
+ second = gc[1]
74
+ print(first.type_string()) # 'Point'
75
+ ```
76
+
77
+ ### Point
78
+
79
+ ```python
80
+ from togo import Point
81
+
82
+ # Create a point
83
+ p = Point(1.0, 2.0)
84
+
85
+ # Access coordinates
86
+ print(f"X: {p.x}, Y: {p.y}")
87
+
88
+ # Get as a tuple
89
+ print(p.as_tuple())
90
+
91
+ # Convert to a Geometry object
92
+ geom = p.as_geometry()
93
+ print(geom.type_string())
94
+ ```
95
+
96
+ ### Segment
97
+
98
+ ```python
99
+ from togo import Segment, Point
100
+
101
+ # Create a segment from two points (or tuples)
102
+ seg = Segment(Point(0, 0), Point(1, 1))
103
+ # Or using tuples
104
+ tuple_seg = Segment((0, 0), (1, 1))
105
+
106
+ # Access endpoints
107
+ print(seg.a) # Point(0, 0)
108
+ print(seg.b) # Point(1, 1)
109
+
110
+ # Get the bounding rectangle
111
+ rect = seg.rect()
112
+ print(rect) # ((0.0, 0.0), (1.0, 1.0))
113
+
114
+ # Check intersection with another segment
115
+ other = Segment((1, 1), (2, 2))
116
+ print(seg.intersects(other)) # True or False
117
+ ```
118
+
119
+ ### Line
120
+
121
+ ```python
122
+ from togo import Line
123
+
124
+ # Create a line from a list of tuples
125
+ line = Line([(0,0), (1,1), (2,0)])
126
+
127
+ # Get number of points
128
+ print(f"Number of points: {line.num_points()}")
129
+
130
+ # Get all points as a list of tuples
131
+ print(f"Points: {line.points()}")
132
+
133
+ # Get the length of the line
134
+ print(f"Length: {line.length()}")
135
+
136
+ # Get the bounding box
137
+ print(f"Bounding box: {line.rect()}")
138
+
139
+ # Get a point by index
140
+ print(f"First point: {line[0].as_tuple()}")
141
+ ```
142
+
143
+ ### Ring
144
+
145
+ ```python
146
+ from togo import Ring
147
+
148
+ # Create a ring (must be closed)
149
+ ring = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
150
+
151
+ # Get area and perimeter
152
+ print(f"Area: {ring.area()}")
153
+ print(f"Perimeter: {ring.perimeter()}")
154
+
155
+ # Check if it's convex or clockwise
156
+ print(f"Is convex: {ring.is_convex()}")
157
+ print(f"Is clockwise: {ring.is_clockwise()}")
158
+
159
+ # Get bounding box
160
+ min_pt, max_pt = ring.rect().min, ring.rect().max
161
+ print(f"Bounding box: {min_pt.as_tuple()}, {max_pt.as_tuple()}")
162
+ ```
163
+
164
+ ### Poly
165
+
166
+ ```python
167
+ from togo import Poly, Ring, Point
168
+
169
+ # Create a polygon with one exterior ring and one interior hole
170
+ exterior = Ring([(0,0), (10,0), (10,10), (0,10), (0,0)])
171
+ hole1 = Ring([(1,1), (2,1), (2,2), (1,2), (1,1)])
172
+ poly = Poly(exterior, holes=[hole1])
173
+
174
+ # Get the exterior ring
175
+ ext_ring = poly.exterior()
176
+ print(f"Exterior has {ext_ring.num_points()} points")
177
+
178
+ # Get number of holes
179
+ print(f"Number of holes: {poly.num_holes()}")
180
+
181
+ # Get a hole by index
182
+ h = poly.hole(0)
183
+ print(f"Hole area: {h.area()}")
184
+
185
+ # A polygon is a geometry, so you can use geometry methods
186
+ geom = poly.as_geometry()
187
+ print(f"Contains point (5,5): {geom.contains(Point(5,5).as_geometry())}")
188
+ # Point is inside the hole, so it is not contained by the polygon
189
+ print(f"Contains point (1.5,1.5): {geom.contains(Point(1.5,1.5).as_geometry())}")
190
+ ```
191
+
192
+ ### MultiGeometries
193
+
194
+ Creating collections of geometries:
195
+
196
+ ```python
197
+ from togo import Geometry, Point, Line, Poly, Ring
198
+
199
+ # Create a MultiPoint
200
+ multi_point = Geometry.from_multipoint([(0,0), (1,1), Point(2,2)])
201
+
202
+ # Create a MultiLineString
203
+ multi_line = Geometry.from_multilinestring([
204
+ [(0,0), (1,1)],
205
+ Line([(2,2), (3,3)])
206
+ ])
207
+
208
+ # Create a MultiPolygon
209
+ poly1 = Poly(Ring([(0,0), (1,0), (1,1), (0,1), (0,0)]))
210
+ poly2 = Poly(Ring([(2,2), (3,2), (3,3), (2,3), (2,2)]))
211
+ multi_poly = Geometry.from_multipolygon([poly1, poly2])
212
+ ```
213
+
214
+ ## Polygon Indexing
215
+
216
+ Togo supports different polygon indexing strategies for optimized spatial operations:
217
+
218
+ ```python
219
+ from togo import TGIndex, set_polygon_indexing_mode
220
+
221
+ # Set the indexing mode
222
+ set_polygon_indexing_mode(TGIndex.NATURAL) # or NONE, YSTRIPES
223
+ ```
224
+
225
+ ## Performance Considerations
226
+
227
+ - Togo is optimized for speed and memory efficiency
228
+ - For large datasets, proper indexing can significantly improve performance
229
+ - Creating geometries with the appropriate format avoids unnecessary conversions
230
+
231
+ Soon there will be a full API documentation, for now please refer to the test suite for more usage examples.
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools>=61",
4
+ "wheel",
5
+ "Cython>=3.0.0",
6
+ ]
7
+ build-backend = "setuptools.build_meta"
8
+
9
+ [project]
10
+ name = "togo"
11
+ version = "0.1.3"
12
+ description = "Lightweight Python bindings for the TG geometry library"
13
+ readme = "README.md"
14
+ authors = [
15
+ {name = "Giorgio Salluzzo", email = "giorgio.salluzzo@gmail.com"}
16
+ ]
17
+ requires-python = ">=3.8"
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: C",
21
+ "Operating System :: POSIX :: Linux",
22
+ "Intended Audience :: Developers",
23
+ "Topic :: Scientific/Engineering :: GIS"
24
+ ]
25
+ dynamic = ["license"]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/mindflayer/togo"
29
+ Source = "https://github.com/mindflayer/togo"
30
+ Tracker = "https://github.com/mindflayer/togo/issues"
31
+
32
+ [tool.pytest.ini_options]
33
+ addopts = "-v -x -q"
34
+ testpaths = ["tests"]
35
+ pythonpath = ["."]
@@ -17,31 +17,36 @@ TG_HEADER_FILENAME = os.path.basename(urlparse(TG_HEADER_URL).path)
17
17
  if not os.path.exists(TG_HEADER_FILENAME):
18
18
  urllib.request.urlretrieve(TG_HEADER_URL, TG_HEADER_FILENAME)
19
19
 
20
- # Package metadata
21
- NAME = "togo"
22
- VERSION = "0.1.0"
23
- DESCRIPTION = "Lightweight Python bindings for the TG geometry library"
24
- LONG_DESCRIPTION = ""
25
- LONG_DESCRIPTION_CONTENT_TYPE = "text/markdown"
26
- if os.path.exists("README.md"):
27
- with open("README.md", "r", encoding="utf-8") as f:
28
- LONG_DESCRIPTION = f.read()
20
+ # Enable optional AddressSanitizer build via env var ASAN=1
21
+ asan_enabled = os.environ.get("ASAN") == "1"
22
+ extra_compile_args = []
23
+ extra_link_args = []
24
+ if asan_enabled:
25
+ # Favor debuggability over speed
26
+ extra_compile_args += [
27
+ "-O1",
28
+ "-g",
29
+ "-fno-omit-frame-pointer",
30
+ "-fsanitize=address",
31
+ ]
32
+ extra_link_args += [
33
+ "-fsanitize=address",
34
+ ]
29
35
 
30
36
  setup(
31
- name=NAME,
32
- version=VERSION,
33
- description=DESCRIPTION,
34
- long_description=LONG_DESCRIPTION,
35
- long_description_content_type=LONG_DESCRIPTION_CONTENT_TYPE,
36
- license="MIT",
37
37
  ext_modules=cythonize(
38
38
  [
39
39
  Extension(
40
40
  "togo",
41
41
  sources=["togo.pyx", TG_SOURCE_FILENAME],
42
42
  include_dirs=["."],
43
+ extra_compile_args=extra_compile_args,
44
+ extra_link_args=extra_link_args,
43
45
  )
44
46
  ]
45
47
  ),
46
- python_requires=">=3.8",
48
+ # Explicitly disable auto-discovery in flat layout
49
+ packages=[],
50
+ py_modules=[],
51
+ license="MIT",
47
52
  )
@@ -94,6 +94,9 @@ def test_geometry_num_lines_polys_geometries():
94
94
  "GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(0 0,1 1))", fmt="wkt"
95
95
  )
96
96
  assert g_collection.num_geometries() == 2
97
+ # Use Geometry.__getitem__ to access sub-geometries of MultiLineString
98
+ first_line = g_lines[0]
99
+ assert first_line.type_string() == "LineString"
97
100
 
98
101
 
99
102
  def test_geometry_z_m():
@@ -156,3 +159,37 @@ def test_geometry_constructor_invalid():
156
159
  Geometry("not a geometry", fmt="geojson")
157
160
  with pytest.raises(ValueError):
158
161
  Geometry("not a geometry", fmt="hex")
162
+
163
+
164
+ def test_geometry_point_accessor():
165
+ g = Geometry("POINT(3 4)", fmt="wkt")
166
+ pt = g.point()
167
+ assert pt.x == 3.0 and pt.y == 4.0
168
+
169
+
170
+ def test_geometry_line_accessor_and_from_linestring():
171
+ points = [(0, 0), (1, 1), (2, 2)]
172
+ g = Geometry.from_linestring(points)
173
+ line = g.line()
174
+ pts = line.points()
175
+ assert pts == points
176
+
177
+
178
+ def test_geometry_poly_accessor():
179
+ # Polygon with one ring
180
+ wkt = "POLYGON((0 0,1 0,1 1,0 1,0 0))"
181
+ g = Geometry(wkt, fmt="wkt")
182
+ poly = g.poly()
183
+ ext = poly.exterior()
184
+ assert ext.num_points() == 5
185
+
186
+
187
+ def test_geometry_geom_at():
188
+ # GeometryCollection with two points
189
+ g = Geometry("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))", fmt="wkt")
190
+ g0 = g[0]
191
+ g1 = g[1]
192
+ assert g0.type_string() == "Point"
193
+ assert g1.type_string() == "Point"
194
+ assert g0.point().x == 1.0 and g0.point().y == 2.0
195
+ assert g1.point().x == 3.0 and g1.point().y == 4.0
@@ -48,3 +48,18 @@ def test_line_as_geometry():
48
48
  assert g.type_string() == "LineString"
49
49
  rect = g.rect()
50
50
  assert rect == ((0.0, 0.0), (2.0, 2.0))
51
+
52
+
53
+ def test_line_getitem():
54
+ points = [(10, 20), (30, 40), (50, 60)]
55
+ line = Line(points)
56
+ pt0 = line[0]
57
+ pt1 = line[1]
58
+ pt2 = line[2]
59
+ assert pt0.x == 10 and pt0.y == 20
60
+ assert pt1.x == 30 and pt1.y == 40
61
+ assert pt2.x == 50 and pt2.y == 60
62
+ with pytest.raises(IndexError):
63
+ _ = line[3]
64
+ with pytest.raises(IndexError):
65
+ _ = line[-1]
@@ -0,0 +1,17 @@
1
+ from togo import Point, Segment
2
+
3
+
4
+ def test_segment_creation_and_rect():
5
+ a = Point(0, 0)
6
+ b = Point(1, 1)
7
+ seg = Segment(a, b)
8
+ rect = seg.rect()
9
+ assert rect == ((0, 0), (1, 1))
10
+
11
+
12
+ def test_segment_intersects():
13
+ seg1 = Segment(Point(0, 0), Point(1, 1))
14
+ seg2 = Segment(Point(0, 1), Point(1, 0))
15
+ seg3 = Segment(Point(2, 2), Point(3, 3))
16
+ assert seg1.intersects(seg2)
17
+ assert not seg1.intersects(seg3)