source: branches/numpy/anuga/utilities/test_polygon.py @ 6768

Last change on this file since 6768 was 6689, checked in by rwilson, 16 years ago

Back-merge from Numeric trunk to numpy branch.

File size: 66.6 KB
RevLine 
[5897]1#!/usr/bin/env python
2
3import unittest
[6304]4import numpy as num
[5897]5from math import sqrt, pi
6from anuga.utilities.numerical_tools import ensure_numeric
7from anuga.utilities.system_tools import get_pathname_from_package
8
9from polygon import *
10from anuga.coordinate_transforms.geo_reference import Geo_reference
11from anuga.geospatial_data.geospatial_data import Geospatial_data
12
[6304]13
[5897]14def test_function(x, y):
15    return x+y
16
[6304]17
[5897]18class Test_Polygon(unittest.TestCase):
19    def setUp(self):
20        pass
21
22    def tearDown(self):
23        pass
24
25    def test_that_C_extension_compiles(self):
26        FN = 'polygon_ext.c'
27        try:
28            import polygon_ext
29        except:
30            from compile import compile
31
32            try:
33                compile(FN)
34            except:
[6304]35                raise Exception, 'Could not compile %s' %FN
[5897]36            else:
37                import polygon_ext
38
39    # Polygon stuff
40    def test_polygon_function_constants(self):
41        p1 = [[0,0], [10,0], [10,10], [0,10]]
42        p2 = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
43
[6304]44        f = Polygon_function([(p1, 1.0)])
45        z = f([5, 5, 27, 35], [5, 9, 8, -5])    # Two first inside p1
46        assert num.allclose(z, [1, 1, 0, 0])
[5897]47
[6304]48        f = Polygon_function([(p2, 2.0)])
49        z = f([5, 5, 27, 35], [5, 9, 8, -5])    # First and last inside p2
50        assert num.allclose(z, [2, 0, 0, 2])
[5897]51
[6304]52        # Combined
53        f = Polygon_function([(p1, 1.0), (p2, 2.0)])
54        z = f([5, 5, 27, 35], [5, 9, 8, -5])
55        assert num.allclose(z, [2, 1, 0, 2])
[5897]56
57    def test_polygon_function_csvfile(self):
58        from os import sep, getenv
59
60        # Get path where this test is run
61        path = get_pathname_from_package('anuga.utilities')
62
63        # Form absolute filename and read
[6304]64        filename = path + sep + 'mainland_only.csv'
65        p1 = read_polygon(filename)
[5897]66
[6304]67        f = Polygon_function([(p1, 10.0)])
68        z = f([430000, 480000], [490000, 7720000]) # 1st outside, 2nd inside
[5897]69
[6304]70        assert num.allclose(z, [0, 10])
71
[5897]72    def test_polygon_function_georef(self):
[6304]73        """Check that georeferencing works"""
[5897]74
75        from anuga.coordinate_transforms.geo_reference import Geo_reference
76
77        geo = Geo_reference(56, 200, 1000)
78
79        # Make points 'absolute'
80        p1 = [[200,1000], [210,1000], [210,1010], [200,1010]]
81        p2 = [[200,1000], [210,1010], [215,1005], [220, 1010], [225,1000],
82              [230,1010], [240,990]]
83
[6304]84        f = Polygon_function([(p1, 1.0)], geo_reference=geo)
85        z = f([5, 5, 27, 35], [5, 9, 8, -5]) # Two first inside p1
[5897]86
[6304]87        assert num.allclose(z, [1, 1, 0, 0])
[5897]88
[6304]89        f = Polygon_function([(p2, 2.0)], geo_reference=geo)
90        z = f([5, 5, 27, 35], [5, 9, 8, -5]) # First and last inside p2
91        assert num.allclose(z, [2, 0, 0, 2])
[5897]92
[6304]93        # Combined
94        f = Polygon_function([(p1, 1.0), (p2, 2.0)], geo_reference=geo)
95        z = f([5, 5, 27, 35], [5, 9, 8, -5])
96        assert num.allclose(z, [2, 1, 0, 2])
[5897]97
[6304]98        # Check that it would fail without geo
99        f = Polygon_function([(p1, 1.0), (p2, 2.0)])
100        z = f([5, 5, 27, 35], [5, 9, 8, -5])
101        assert not num.allclose(z, [2, 1, 0, 2])
[5897]102
[6304]103    def test_polygon_function_callable(self):
104        """Check that values passed into Polygon_function can be callable."""
[5897]105
106        p1 = [[0,0], [10,0], [10,10], [0,10]]
107        p2 = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
108
[6304]109        f = Polygon_function([(p1, test_function)])
110        z = f([5, 5, 27, 35], [5, 9, 8, -5]) # Two first inside p1
111        assert num.allclose(z, [10, 14, 0, 0])
[5897]112
[6304]113        # Combined
114        f = Polygon_function([(p1, test_function), (p2, 2.0)])
115        z = f([5, 5, 27, 35], [5, 9, 8, -5])
116        assert num.allclose(z, [2, 14, 0, 2])
[5897]117
[6304]118        # Combined w default
119        f = Polygon_function([(p1, test_function), (p2, 2.0)], default = 3.14)
120        z = f([5, 5, 27, 35], [5, 9, 8, -5])
121        assert num.allclose(z, [2, 14, 3.14, 2])
[5897]122
[6304]123        # Combined w default func
124        f = Polygon_function([(p1, test_function), (p2, 2.0)],
125                             default=test_function)
126        z = f([5, 5, 27, 35], [5, 9, 8, -5])
127        assert num.allclose(z, [2, 14, 35, 2])
[5897]128
129    def test_point_on_line(self):
[6304]130        # Endpoints first
131        assert point_on_line([0,0], [[0,0], [1,0]])
132        assert point_on_line([1,0], [[0,0], [1,0]])
[5897]133
[6304]134        # Endpoints first - non-simple
135        assert point_on_line([-0.1,0.0], [[-0.1,0.0], [1.5,0.6]])
136        assert point_on_line([1.5,0.6], [[-0.1,0.0], [1.5,0.6]])
[5897]137
[6304]138        # Then points on line
139        assert point_on_line([0.5,0], [[0,0], [1,0]])
140        assert point_on_line([0,0.5], [[0,1], [0,0]])
141        assert point_on_line([1,0.5], [[1,1], [1,0]])
142        assert point_on_line([0.5,0.5], [[0,0], [1,1]])
[5897]143
[6304]144        # Then points not on line
145        assert not point_on_line([0.5,0], [[0,1], [1,1]])
146        assert not point_on_line([0,0.5], [[0,0], [1,1]])
[5897]147
[6304]148        # From real example that failed
149        assert not point_on_line([40,50], [[40,20], [40,40]])
[5897]150
[6304]151        # From real example that failed
152        assert not point_on_line([40,19], [[40,20], [40,40]])
[5897]153
154        # Degenerate line
[6304]155        assert point_on_line([40,19], [[40,19], [40,19]])
156        assert not point_on_line([40,19], [[40,40], [40,40]])
[5897]157
158    def test_is_inside_polygon_main(self):
159        # Simplest case: Polygon is the unit square
160        polygon = [[0,0], [1,0], [1,1], [0,1]]
161
[6304]162        assert is_inside_polygon((0.5, 0.5), polygon)
163        assert not is_inside_polygon((0.5, 1.5), polygon)
164        assert not is_inside_polygon((0.5, -0.5), polygon)
165        assert not is_inside_polygon((-0.5, 0.5), polygon)
166        assert not is_inside_polygon((1.5, 0.5), polygon)
[5897]167
[6304]168        # Try point on borders
169        assert is_inside_polygon((1., 0.5), polygon, closed=True)
170        assert is_inside_polygon((0.5, 1.), polygon, closed=True)
171        assert is_inside_polygon((0., 0.5), polygon, closed=True)
172        assert is_inside_polygon((0.5, 0.), polygon, closed=True)
[5897]173
[6304]174        assert not is_inside_polygon((0.5, 1.), polygon, closed=False)
175        assert not is_inside_polygon((0., 0.5), polygon, closed=False)
176        assert not is_inside_polygon((0.5, 0.), polygon, closed=False)
177        assert not is_inside_polygon((1., 0.5), polygon, closed=False)
[5897]178
179    def test_inside_polygon_main(self):
180        # Simplest case: Polygon is the unit square
[6304]181        polygon = [[0,0], [1,0], [1,1], [0,1]]
[5897]182
[6553]183        assert is_inside_polygon_quick( (0.5, 0.5), polygon )
184        assert not is_inside_polygon_quick( (0.5, 1.5), polygon )
185        assert not is_inside_polygon_quick( (0.5, -0.5), polygon )
186        assert not is_inside_polygon_quick( (-0.5, 0.5), polygon )
187        assert not is_inside_polygon_quick( (1.5, 0.5), polygon )
188
189        # Try point on borders
190        assert is_inside_polygon_quick( (1., 0.5), polygon, closed=True)
191        assert is_inside_polygon_quick( (0.5, 1), polygon, closed=True)
192        assert is_inside_polygon_quick( (0., 0.5), polygon, closed=True)
193        assert is_inside_polygon_quick( (0.5, 0.), polygon, closed=True)
194
195        assert not is_inside_polygon_quick( (0.5, 1), polygon, closed=False)
196        assert not is_inside_polygon_quick( (0., 0.5), polygon, closed=False)
197        assert not is_inside_polygon_quick( (0.5, 0.), polygon, closed=False)
198        assert not is_inside_polygon_quick( (1., 0.5), polygon, closed=False)
199
200
201    def test_inside_polygon_main(self):
202        # Simplest case: Polygon is the unit square
203        polygon = [[0,0], [1,0], [1,1], [0,1]]
204
[5897]205        # From real example (that failed)
[6304]206        polygon = [[20,20], [40,20], [40,40], [20,40]]
207        points = [[40, 50]]
208        res = inside_polygon(points, polygon)
209        assert len(res) == 0
[5897]210
[6304]211        polygon = [[20,20], [40,20], [40,40], [20,40]]
212        points = [[25, 25], [30, 20], [40, 50], [90, 20], [40, 90]]
213        res = inside_polygon(points, polygon)
214        assert len(res) == 2
215        assert num.allclose(res, [0,1])
[5897]216
[6304]217        # More convoluted and non convex polygon
[5897]218        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
[6553]219        assert is_inside_polygon( (0.5, 0.5), polygon )
220        assert is_inside_polygon( (1, -0.5), polygon )
221        assert is_inside_polygon( (1.5, 0), polygon )
[5897]222
[6553]223        assert not is_inside_polygon( (0.5, 1.5), polygon )
224        assert not is_inside_polygon( (0.5, -0.5), polygon )
[5897]225
[6553]226        assert is_inside_polygon_quick( (0.5, 0.5), polygon )
227        assert is_inside_polygon_quick( (1, -0.5), polygon )
228        assert is_inside_polygon_quick( (1.5, 0), polygon )
229
230        assert not is_inside_polygon_quick( (0.5, 1.5), polygon )
231        assert not is_inside_polygon_quick( (0.5, -0.5), polygon )
232
[6304]233        # Very convoluted polygon
[5897]234        polygon = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
[6304]235        assert is_inside_polygon((5, 5), polygon)
236        assert is_inside_polygon((17, 7), polygon)
237        assert is_inside_polygon((27, 2), polygon)
238        assert is_inside_polygon((35, -5), polygon)
239        assert not is_inside_polygon((15, 7), polygon)
240        assert not is_inside_polygon((24, 3), polygon)
241        assert not is_inside_polygon((25, -10), polygon)
[5897]242
[6304]243        # Another combination (that failed)
[5897]244        polygon = [[0,0], [10,0], [10,10], [0,10]]
[6304]245        assert is_inside_polygon((5, 5), polygon)
246        assert is_inside_polygon((7, 7), polygon)
247        assert not is_inside_polygon((-17, 7), polygon)
248        assert not is_inside_polygon((7, 17), polygon)
249        assert not is_inside_polygon((17, 7), polygon)
250        assert not is_inside_polygon((27, 8), polygon)
251        assert not is_inside_polygon((35, -5), polygon)
[5897]252
[6304]253        # Multiple polygons
254        polygon = [[0,0], [1,0], [1,1], [0,1], [0,0], [10,10],
255                   [11,10], [11,11], [10,11], [10,10]]
256        assert is_inside_polygon((0.5, 0.5), polygon)
257        assert is_inside_polygon((10.5, 10.5), polygon)
[5897]258
[6304]259        # FIXME: Fails if point is 5.5, 5.5
260        assert not is_inside_polygon((0, 5.5), polygon)
[5897]261
[6304]262        # Polygon with a hole
[5897]263        polygon = [[-1,-1], [2,-1], [2,2], [-1,2], [-1,-1],
[6304]264                   [0,0], [1,0], [1,1], [0,1], [0,0]]
[5897]265
[6304]266        assert is_inside_polygon((0, -0.5), polygon)
267        assert not is_inside_polygon((0.5, 0.5), polygon)
[5897]268
269    def test_duplicate_points_being_ok(self):
270        # Simplest case: Polygon is the unit square
271        polygon = [[0,0], [1,0], [1,0], [1,0], [1,1], [0,1], [0,0]]
272
[6304]273        assert is_inside_polygon((0.5, 0.5), polygon)
274        assert not is_inside_polygon((0.5, 1.5), polygon)
275        assert not is_inside_polygon((0.5, -0.5), polygon)
276        assert not is_inside_polygon((-0.5, 0.5), polygon)
277        assert not is_inside_polygon((1.5, 0.5), polygon)
[5897]278
[6304]279        # Try point on borders
280        assert is_inside_polygon((1., 0.5), polygon, closed=True)
281        assert is_inside_polygon((0.5, 1), polygon, closed=True)
282        assert is_inside_polygon((0., 0.5), polygon, closed=True)
283        assert is_inside_polygon((0.5, 0.), polygon, closed=True)
[5897]284
[6304]285        assert not is_inside_polygon((0.5, 1), polygon, closed=False)
286        assert not is_inside_polygon((0., 0.5), polygon, closed=False)
287        assert not is_inside_polygon((0.5, 0.), polygon, closed=False)
288        assert not is_inside_polygon((1., 0.5), polygon, closed=False)
[5897]289
290        # From real example
[6304]291        polygon = [[20,20], [40,20], [40,40], [20,40]]
292        points = [[40, 50]]
293        res = inside_polygon(points, polygon)
294        assert len(res) == 0
[5897]295
296    def test_inside_polygon_vector_version(self):
[6304]297        # Now try the vector formulation returning indices
[5897]298        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
[6304]299        points = [[0.5, 0.5], [1, -0.5], [1.5, 0], [0.5, 1.5], [0.5, -0.5]]
300        res = inside_polygon( points, polygon, verbose=False )
301        assert num.allclose( res, [0,1,2] )
[5897]302
303    def test_outside_polygon(self):
[6304]304        # unit square
305        U = [[0,0], [1,0], [1,1], [0,1]]
[5897]306
307        # evaluate to False as the point 0.5, 0.5 is inside the unit square
[6304]308        assert not is_outside_polygon([0.5, 0.5], U)
309
[5897]310        # evaluate to True as the point 1.5, 0.5 is outside the unit square
[6304]311        assert is_outside_polygon([1.5, 0.5], U)
312
313        indices = outside_polygon([[0.5, 0.5], [1, -0.5], [0.3, 0.2]], U)
314        assert num.allclose(indices, [1])
315
[5897]316        # One more test of vector formulation returning indices
317        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
[6304]318        points = [[0.5, 0.5], [1, -0.5], [1.5, 0], [0.5, 1.5], [0.5, -0.5]]
319        res = outside_polygon(points, polygon)
320        assert num.allclose(res, [3, 4])
[5897]321
[6304]322        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
323        points = [[0.5, 1.4], [0.5, 0.5], [1, -0.5], [1.5, 0],
324                  [0.5, 1.5], [0.5, -0.5]]
325        res = outside_polygon(points, polygon)
[5897]326
[6304]327        assert num.allclose(res, [0, 4, 5])
[5897]328
[6304]329    def test_outside_polygon2(self):
330        # unit square
331        U = [[0,0], [1,0], [1,1], [0,1]]
[5897]332
[6304]333        # evaluate to False as the point 0.5, 1.0 is inside the unit square
334        assert not outside_polygon([0.5, 1.0], U, closed = True)
[5897]335
336        # evaluate to True as the point 0.5, 1.0 is outside the unit square
[6304]337        assert is_outside_polygon([0.5, 1.0], U, closed = False)
[5897]338
339    def test_all_outside_polygon(self):
[6304]340        """Test case where all points are outside poly"""
[5897]341
[6304]342        # unit square
343        U = [[0,0], [1,0], [1,1], [0,1]]
[5897]344
[6304]345        points = [[2,2], [1,3], [-1,1], [0,2]]      # All outside
[5897]346
347        indices, count = separate_points_by_polygon(points, U)
[6304]348        assert count == 0                           # None inside
349        assert num.allclose(indices, [3, 2, 1, 0])
[5897]350
351        indices = outside_polygon(points, U, closed = True)
[6304]352        assert num.allclose(indices, [0, 1, 2, 3])
[5897]353
354        indices = inside_polygon(points, U, closed = True)
[6304]355        assert num.allclose(indices, [])
[5897]356
357    def test_all_inside_polygon(self):
[6304]358        """Test case where all points are inside poly"""
[5897]359
[6304]360        # unit square
361        U = [[0,0], [1,0], [1,1], [0,1]]
[5897]362
[6304]363        points = [[0.5,0.5], [0.2,0.3], [0,0.5]]    # All inside (or on edge)
[5897]364
365        indices, count = separate_points_by_polygon(points, U)
[6304]366        assert count == 3       # All inside
367        assert num.allclose(indices, [0, 1, 2])
[5897]368
[6304]369        indices = outside_polygon(points, U, closed=True)
[6158]370        assert num.allclose(indices, [])
[5897]371
[6304]372        indices = inside_polygon(points, U, closed=True)
373        assert num.allclose(indices, [0, 1, 2])
[5897]374
[6304]375
[5897]376    def test_separate_points_by_polygon(self):
[6304]377        # unit square
378        U = [[0,0], [1,0], [1,1], [0,1]]
[5897]379
[6304]380        indices, count = separate_points_by_polygon([[0.5, 0.5],
381                                                     [1, -0.5],
382                                                     [0.3, 0.2]],
383                                                    U)
384        assert num.allclose( indices, [0, 2, 1] )
[5897]385        assert count == 2
[6304]386
387        # One more test of vector formulation returning indices
[5897]388        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
[6304]389        points = [[0.5, 0.5], [1, -0.5], [1.5, 0], [0.5, 1.5], [0.5, -0.5]]
390        res, count = separate_points_by_polygon(points, polygon)
[5897]391
[6304]392        assert num.allclose(res, [0, 1, 2, 4, 3])
393        assert count == 3
[5897]394
395        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
[6553]396        points = [ [0.5, 1.4], [0.5, 0.5], [1, -0.5], [1.5, 0], [0.5, 1.5], [0.5, -0.5]]
397        res, count = separate_points_by_polygon( points, polygon )
[5897]398
[6553]399        assert num.allclose( res, [1,2,3,5,4,0] )
[6304]400        assert count == 3
[5897]401
[6553]402
403    def test_is_inside_triangle(self):
404        # Simplest case:
405        triangle = [[0, 0], [1, 0], [0.5, 1]]
406
407        assert is_inside_triangle((0.5, 0.5), triangle)
408        assert is_inside_triangle((0.9, 0.1), triangle)
409        assert not is_inside_triangle((0.5, 1.5), triangle)
410        assert not is_inside_triangle((0.5, -0.5), triangle)
411        assert not is_inside_triangle((-0.5, 0.5), triangle)
412        assert not is_inside_triangle((1.5, 0.5), triangle)
413
414        # Try point on borders
415        assert is_inside_triangle((0.5, 0), triangle, closed=True)
416        assert is_inside_triangle((1, 0), triangle, closed=True)
417
418        assert not is_inside_triangle((0.5, 0), triangle, closed=False)
419        assert not is_inside_triangle((1, 0), triangle, closed=False)
420
421        # Try vertices
422        for P in triangle:
423            assert is_inside_triangle(P, triangle, closed=True)
424            assert not is_inside_triangle(P, triangle, closed=False)
425
426        # Slightly different
427        triangle = [[0, 0.1], [1, -0.2], [0.5, 1]]
428        assert is_inside_triangle((0.5, 0.5), triangle)
429        assert is_inside_triangle((0.4, 0.1), triangle)
430        assert not is_inside_triangle((1, 1), triangle)
431
432        # Try vertices
433        for P in triangle:
434            assert is_inside_triangle(P, triangle, closed=True)
435            assert not is_inside_triangle(P, triangle, closed=False)
436
437
[5897]438    def test_populate_polygon(self):
439        polygon = [[0,0], [1,0], [1,1], [0,1]]
440        points = populate_polygon(polygon, 5)
441
442        assert len(points) == 5
443        for point in points:
444            assert is_inside_polygon(point, polygon)
445
[6553]446            assert is_inside_polygon_quick(point, polygon)
447
448
[6304]449        # Very convoluted polygon
[5897]450        polygon = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
451        points = populate_polygon(polygon, 5)
452        assert len(points) == 5
453        for point in points:
454            assert is_inside_polygon(point, polygon)
[6553]455            assert is_inside_polygon_quick(point, polygon)
[5897]456
[6553]457
[5897]458    def test_populate_polygon_with_exclude(self):
459        polygon = [[0,0], [1,0], [1,1], [0,1]]
[6304]460        ex_poly = [[0,0], [0.5,0], [0.5, 0.5], [0,0.5]]     # SW quarter
461        points = populate_polygon(polygon, 5, exclude=[ex_poly])
[5897]462
463        assert len(points) == 5
464        for point in points:
465            assert is_inside_polygon(point, polygon)
[6304]466            assert not is_inside_polygon(point, ex_poly)
[5897]467
[6304]468        # overlap
[5897]469        polygon = [[0,0], [1,0], [1,1], [0,1]]
470        ex_poly = [[-1,-1], [0.5,0], [0.5, 0.5], [-1,0.5]]
[6304]471        points = populate_polygon(polygon, 5, exclude=[ex_poly])
[5897]472
473        assert len(points) == 5
474        for point in points:
475            assert is_inside_polygon(point, polygon)
[6304]476            assert not is_inside_polygon(point, ex_poly)
477
478        # Multiple
[5897]479        polygon = [[0,0], [1,0], [1,1], [0,1]]
[6304]480        ex_poly1 = [[0,0], [0.5,0], [0.5, 0.5], [0,0.5]]    # SW quarter
481        ex_poly2 = [[0.5,0.5], [0.5,1], [1, 1], [1,0.5]]    # NE quarter
[5897]482
[6304]483        points = populate_polygon(polygon, 20, exclude=[ex_poly1, ex_poly2])
484
[5897]485        assert len(points) == 20
486        for point in points:
487            assert is_inside_polygon(point, polygon)
488            assert not is_inside_polygon(point, ex_poly1)
[6304]489            assert not is_inside_polygon(point, ex_poly2)
[5897]490
[6304]491        # Very convoluted polygon
[5897]492        polygon = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
493        ex_poly = [[-1,-1], [5,0], [5, 5], [-1,5]]
[6304]494        points = populate_polygon(polygon, 20, exclude=[ex_poly])
495
[5897]496        assert len(points) == 20
497        for point in points:
498            assert is_inside_polygon(point, polygon)
[6304]499            assert not is_inside_polygon(point, ex_poly), '%s' % str(point)
[5897]500
501    def test_populate_polygon_with_exclude2(self):
[6304]502        min_outer = 0
[5897]503        max_outer = 1000
[6304]504        polygon_outer = [[min_outer,min_outer], [max_outer,min_outer],
505                         [max_outer,max_outer], [min_outer,max_outer]]
[5897]506
507        delta = 10
508        min_inner1 = min_outer + delta
509        max_inner1 = max_outer - delta
[6304]510        inner1_polygon = [[min_inner1,min_inner1], [max_inner1,min_inner1],
511                          [max_inner1,max_inner1], [min_inner1,max_inner1]]
[5897]512
[6304]513        density_inner2 = 1000
514        min_inner2 = min_outer + 2*delta
515        max_inner2 = max_outer - 2*delta
516        inner2_polygon = [[min_inner2,min_inner2], [max_inner2,min_inner2],
517                          [max_inner2,max_inner2], [min_inner2,max_inner2]]
518
519        points = populate_polygon(polygon_outer, 20,
520                                  exclude=[inner1_polygon, inner2_polygon])
521
[5897]522        assert len(points) == 20
523        for point in points:
524            assert is_inside_polygon(point, polygon_outer)
525            assert not is_inside_polygon(point, inner1_polygon)
[6304]526            assert not is_inside_polygon(point, inner2_polygon)
[5897]527
[6304]528        # Very convoluted polygon
[5897]529        polygon = [[0,0], [10,10], [15,5], [20, 10], [25,0], [30,10], [40,-10]]
530        ex_poly = [[-1,-1], [5,0], [5, 5], [-1,5]]
[6304]531        points = populate_polygon(polygon, 20, exclude=[ex_poly])
532
[5897]533        assert len(points) == 20
534        for point in points:
535            assert is_inside_polygon(point, polygon)
[6304]536            assert not is_inside_polygon(point, ex_poly), '%s' % str(point)
[5897]537
538    def test_point_in_polygon(self):
539        polygon = [[0,0], [1,0], [1,1], [0,1]]
540        point = point_in_polygon(polygon)
541        assert is_inside_polygon(point, polygon)
542
[6304]543        # this may get into a vicious loop
544        # polygon = [[1e32,1e54], [1,0], [1,1], [0,1]]
545
[5897]546        polygon = [[1e15,1e7], [1,0], [1,1], [0,1]]
547        point = point_in_polygon(polygon)
548        assert is_inside_polygon(point, polygon)
549
550        polygon = [[0,0], [1,0], [1,1], [1e8,1e8]]
551        point = point_in_polygon(polygon)
552        assert is_inside_polygon(point, polygon)
553
554        polygon = [[1e32,1e54], [-1e32,1e54], [1e32,-1e54]]
555        point = point_in_polygon(polygon)
556        assert is_inside_polygon(point, polygon)
557
558        polygon = [[1e18,1e15], [1,0], [0,1]]
559        point = point_in_polygon(polygon)
560        assert is_inside_polygon(point, polygon)
561
562    def test_in_and_outside_polygon_main(self):
[6304]563        # Simplest case: Polygon is the unit square
564        polygon = [[0,0], [1,0], [1,1], [0,1]]
[5897]565
[6304]566        inside, outside = in_and_outside_polygon((0.5, 0.5), polygon)
567        assert inside[0] == 0
568        assert len(outside) == 0
[5897]569
[6304]570        inside, outside = in_and_outside_polygon((1., 0.5), polygon,
571                                                 closed=True)
572        assert inside[0] == 0
573        assert len(outside) == 0
[5897]574
[6304]575        inside, outside = in_and_outside_polygon((1., 0.5), polygon,
576                                                 closed=False)
577        assert len(inside) == 0
578        assert outside[0] == 0
[5897]579
[6304]580        points = [(1., 0.25),(1., 0.75)]
581        inside, outside = in_and_outside_polygon(points, polygon, closed=True)
582        assert (inside, [0,1])
583        assert len(outside) == 0
[5897]584
[6304]585        inside, outside = in_and_outside_polygon(points, polygon, closed=False)
586        assert len(inside) == 0
587        assert (outside, [0,1])
[5897]588
[6304]589        points = [(100., 0.25), (0.5, 0.5) ]
590        inside, outside = in_and_outside_polygon(points, polygon)
591        assert (inside, [1])
592        assert outside[0] == 0
[5897]593
[6304]594        points = [(100., 0.25),(0.5, 0.5), (39,20), (0.6,0.7),(56,43),(67,90)]
595        inside, outside = in_and_outside_polygon(points, polygon)
596        assert (inside, [1, 3])
597        assert (outside, [0, 2, 4, 5])
598
[5897]599    def test_intersection1(self):
600        line0 = [[-1,0], [1,0]]
601        line1 = [[0,-1], [0,1]]
602
603        status, value = intersection(line0, line1)
604        assert status == 1
[6158]605        assert num.allclose(value, [0.0, 0.0])
[5897]606
607    def test_intersection2(self):
608        line0 = [[0,0], [24,12]]
609        line1 = [[0,12], [24,0]]
610
611        status, value = intersection(line0, line1)
612        assert status == 1
[6158]613        assert num.allclose(value, [12.0, 6.0])
[5897]614
615        # Swap direction of one line
616        line1 = [[24,0], [0,12]]
617
618        status, value = intersection(line0, line1)
619        assert status == 1
[6158]620        assert num.allclose(value, [12.0, 6.0])
[5897]621
622        # Swap order of lines
623        status, value = intersection(line1, line0)
624        assert status == 1
[6304]625        assert num.allclose(value, [12.0, 6.0])
626
[5897]627    def test_intersection3(self):
628        line0 = [[0,0], [24,12]]
629        line1 = [[0,17], [24,0]]
630
631        status, value = intersection(line0, line1)
632        assert status == 1
[6158]633        assert num.allclose(value, [14.068965517, 7.0344827586])
[5897]634
635        # Swap direction of one line
636        line1 = [[24,0], [0,17]]
637
638        status, value = intersection(line0, line1)
639        assert status == 1
[6304]640        assert num.allclose(value, [14.068965517, 7.0344827586])
[5897]641
642        # Swap order of lines
643        status, value = intersection(line1, line0)
[6304]644        assert status == 1
645        assert num.allclose(value, [14.068965517, 7.0344827586])
[5897]646
647    def test_intersection_endpoints(self):
648        """test_intersection_endpoints(self):
649
650        Test that coinciding endpoints are picked up
651        """
[6304]652
[5897]653        line0 = [[0,0], [1,1]]
654        line1 = [[1,1], [2,1]]
655
656        status, value = intersection(line0, line1)
657        assert status == 1
[6158]658        assert num.allclose(value, [1.0, 1.0])
[5897]659
660        line0 = [[1,1], [2,0]]
661        line1 = [[1,1], [2,1]]
662
663        status, value = intersection(line0, line1)
664        assert status == 1
[6304]665        assert num.allclose(value, [1.0, 1.0])
[5897]666
[5942]667    # This function is a helper function for
668    # the test_intersection_bug_20081110_?() set of tests.
669    # This function tests all parallel line cases for 4 collinear points.
[5933]670    # This function should never be run directly by the unittest code.
671    def helper_test_parallel_intersection_code(self, P1, P2, P3, P4):
672        # lines in same direction, no overlap
673        # 0:         ---->----
674        # 1:                     --------->-----------
[6304]675        line0 = [P1, P2]
676        line1 = [P3, P4]
[5933]677        status, value = intersection(line0, line1)
678        self.failIf(status!=3, 'Expected status 3, got status=%s, value=%s' %
679                               (str(status), str(value)))
680        self.failUnless(value is None, 'Expected value of None, got %s' %
681                                       str(value))
682
683        # lines in same direction, no overlap
684        # 0:         ----<----
685        # 1:                     ---------<-----------
[6304]686        line0 = [P2, P1]
687        line1 = [P4, P3]
[5933]688        status, value = intersection(line0, line1)
689        self.failIf(status!=3, 'Expected status 3, got status=%s, value=%s' %
690                               (str(status), str(value)))
691        self.failUnless(value is None, 'Expected value of None, got %s' %
692                                       str(value))
693
694        # lines in opposite direction, no overlap
695        # 0:         ----<----
696        # 1:                     --------->-----------
[6304]697        line0 = [P2, P1]
698        line1 = [P3, P4]
[5933]699        status, value = intersection(line0, line1)
700        self.failIf(status!=3, 'Expected status 3, got status=%s, value=%s' %
701                               (str(status), str(value)))
702        self.failUnless(value is None, 'Expected value of None, got %s' %
703                                       str(value))
704
705        # lines in opposite direction, no overlap
706        # 0:         ---->----
707        # 1:                     ---------<-----------
[6304]708        line0 = [P1, P2]
709        line1 = [P4, P3]
[5933]710        status, value = intersection(line0, line1)
711        self.failIf(status!=3, 'Expected status 3, got status=%s, value=%s' %
712                               (str(status), str(value)))
713        self.failUnless(value is None, 'Expected value of None, got %s' %
714                                       str(value))
715
[6304]716        # ----------------------------------------------------------------------
[5942]717
[5933]718        # line0 fully within line1, same direction
719        # 0:         ---->----
720        # 1:    --------->-----------
721        # value should be line0:
722        #            ---->----
[6304]723        line0 = [P2, P3]
724        line1 = [P1, P4]
[5933]725        status, value = intersection(line0, line1)
726        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
727                               (str(status), str(value)))
[6158]728        self.failUnless(num.allclose(value, line0))
[5933]729
730        # line0 fully within line1, same direction
731        # 0:         ----<----
732        # 1:    ---------<-----------
733        # value should be line0:
734        #            ----<----
[6304]735        line0 = [P3, P2]
736        line1 = [P4, P1]
[5933]737        status, value = intersection(line0, line1)
738        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
739                               (str(status), str(value)))
[6158]740        self.failUnless(num.allclose(value, line0))
[5933]741
742        # line0 fully within line1, opposite direction
743        # 0:         ----<----
744        # 1:    --------->-----------
745        # value should be line0:
746        #            ----<----
[6304]747        line0 = [P3, P2]
748        line1 = [P1, P4]
[5933]749        status, value = intersection(line0, line1)
750        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
751                               (str(status), str(value)))
[6158]752        self.failUnless(num.allclose(value, line0))
[5933]753
754        # line0 fully within line1, opposite direction
755        # 0:         ---->----
756        # 1:    ---------<-----------
757        # value should be line0:
758        #            ---->----
[6304]759        line0 = [P2, P3]
760        line1 = [P4, P1]
[5933]761        status, value = intersection(line0, line1)
762        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
763                               (str(status), str(value)))
[6158]764        self.failUnless(num.allclose(value, line0))
[5933]765
[6304]766        # ----------------------------------------------------------------------
[5942]767
[5933]768        # line1 fully within line0, same direction
769        # 0:    --------->-----------
770        # 1:         ---->----
771        # value should be line1:
772        #            ---->----
[6304]773        line0 = [P1, P4]
774        line1 = [P2, P3]
[5933]775        status, value = intersection(line0, line1)
776        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
777                               (str(status), str(value)))
[6158]778        self.failUnless(num.allclose(value, line1))
[5933]779
780        # line1 fully within line0, same direction
781        # 0:    ---------<-----------
782        # 1:         ----<----
783        # value should be line1:
784        #            ----<----
[6304]785        line0 = [P4, P1]
786        line1 = [P3, P2]
[5933]787        status, value = intersection(line0, line1)
788        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
789                               (str(status), str(value)))
[6158]790        self.failUnless(num.allclose(value, line1))
[5933]791
792        # line1 fully within line0, opposite direction
793        # 0:    ---------<-----------
794        # 1:         ---->----
795        # value should be line1:
796        #            ---->----
[6304]797        line0 = [P4, P1]
798        line1 = [P2, P3]
[5933]799        status, value = intersection(line0, line1)
800        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
801                               (str(status), str(value)))
[6158]802        self.failUnless(num.allclose(value, line1))
[5933]803
804        # line1 fully within line0, opposite direction
805        # 0:    --------->-----------
806        # 1:         ----<----
807        # value should be line1:
808        #            ----<----
[6304]809        line0 = [P1, P4]
810        line1 = [P3, P2]
[5933]811        status, value = intersection(line0, line1)
812        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
813                               (str(status), str(value)))
[6158]814        self.failUnless(num.allclose(value, line1))
[5933]815
[6304]816        # ----------------------------------------------------------------------
[5942]817
[5933]818        # line in same direction, partial overlap
819        # 0:    ----->-----
820        # 1:       ------->--------
821        # value should be segment line1_start->line0_end:
822        #          --->----
[6304]823        line0 = [P1, P3]
824        line1 = [P2, P4]
[5933]825        status, value = intersection(line0, line1)
826        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
827                               (str(status), str(value)))
[6158]828        self.failUnless(num.allclose(value, [line1[0],line0[1]]))
[5933]829
830        # line in same direction, partial overlap
831        # 0:    -----<-----
832        # 1:       -------<--------
833        # value should be segment line0_start->line1_end:
834        #          ---<----
[6304]835        line0 = [P3, P1]
836        line1 = [P4, P2]
[5933]837        status, value = intersection(line0, line1)
838        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
839                               (str(status), str(value)))
[6158]840        self.failUnless(num.allclose(value, [line0[0],line1[1]]))
[5933]841
842        # line in opposite direction, partial overlap
843        # 0:    -----<-----
844        # 1:       ------->--------
845        # value should be segment line0_start->line1_start:
846        #          ---<----
[6304]847        line0 = [P3, P1]
848        line1 = [P2, P4]
[5933]849        status, value = intersection(line0, line1)
850        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
851                               (str(status), str(value)))
[6158]852        self.failUnless(num.allclose(value, [line0[0],line1[0]]))
[5933]853
854        # line in opposite direction, partial overlap
855        # 0:    ----->-----
856        # 1:       -------<--------
857        # value should be segment line1_end->line0_end:
858        #          --->----
[6304]859        line0 = [P1, P3]
860        line1 = [P4, P2]
[5933]861        status, value = intersection(line0, line1)
862        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
863                               (str(status), str(value)))
[6158]864        self.failUnless(num.allclose(value, [line1[1],line0[1]]))
[5933]865
[6304]866        # ----------------------------------------------------------------------
[5942]867
[5933]868        # line in same direction, partial overlap
869        # 0:       ------>------
870        # 1:    ------>------
871        # value should be segment line0_start->line1_end:
872        #          --->----
[6304]873        line0 = [P2, P4]
874        line1 = [P1, P3]
[5933]875        status, value = intersection(line0, line1)
876        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
877                               (str(status), str(value)))
[6158]878        self.failUnless(num.allclose(value, [line0[0],line1[1]]))
[5933]879
880        # line in same direction, partial overlap
881        # 0:       ------<------
882        # 1:    ------<------
883        # value should be segment line1_start->line0_end:
884        #          ----<-----
[6304]885        line0 = [P4, P2]
886        line1 = [P3, P1]
[5933]887        status, value = intersection(line0, line1)
888        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
889                               (str(status), str(value)))
[6158]890        self.failUnless(num.allclose(value, [line1[0],line0[1]]))
[5933]891
892        # line in opposite direction, partial overlap
893        # 0:       ------<------
894        # 1:    ----->------
895        # value should be segment line1_end->line0_end:
896        #          --->----
[6304]897        line0 = [P4, P2]
898        line1 = [P1, P3]
[5933]899        status, value = intersection(line0, line1)
900        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
901                               (str(status), str(value)))
[6158]902        self.failUnless(num.allclose(value, [line1[1],line0[1]]))
[5933]903
904        # line in opposite direction, partial overlap
905        # 0:       ------>------
906        # 1:    -----<------
907        # value should be segment line0_start->line1_start:
908        #          ---<----
[6304]909        line0 = [P2, P4]
910        line1 = [P3, P1]
[5933]911        status, value = intersection(line0, line1)
912        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
913                               (str(status), str(value)))
[6158]914        self.failUnless(num.allclose(value, [line0[0],line1[0]]))
[5933]915
[6304]916        # ----------------------------------------------------------------------
[5942]917
918        # line in same direction, same left point, line1 longer
919        # 0:    ----->------
920        # 1:    ------->--------
921        # value should be line0:
922        #       ----->------
[6304]923        line0 = [P1, P3]
924        line1 = [P1, P4]
[5942]925        status, value = intersection(line0, line1)
926        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
927                               (str(status), str(value)))
[6158]928        self.failUnless(num.allclose(value, line0))
[5942]929
930        # line in same direction, same left point, line1 longer
931        # 0:    -----<------
932        # 1:    -------<--------
933        # value should be line0:
934        #       -----<------
[6304]935        line0 = [P3, P1]
936        line1 = [P4, P1]
[5942]937        status, value = intersection(line0, line1)
938        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
939                               (str(status), str(value)))
[6158]940        self.failUnless(num.allclose(value, line0))
[5942]941
942        # line in opposite direction, same left point, line1 longer
943        # 0:    ----->------
944        # 1:    -------<--------
945        # value should be line0:
946        #       ----->------
[6304]947        line0 = [P1, P3]
948        line1 = [P4, P1]
[5942]949        status, value = intersection(line0, line1)
950        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
951                               (str(status), str(value)))
[6158]952        self.failUnless(num.allclose(value, line0))
[5942]953
954        # line in opposite direction, same start point, line1 longer
955        # 0:    -----<------
956        # 1:    ------->--------
957        # value should be line0:
958        #       -----<------
[6304]959        line0 = [P3, P1]
960        line1 = [P1, P4]
[5942]961        status, value = intersection(line0, line1)
962        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
963                               (str(status), str(value)))
[6158]964        self.failUnless(num.allclose(value, line0))
[5942]965
[6304]966        # ----------------------------------------------------------------------
[5942]967
968        # line in same direction, same left point, same right point
969        # 0:    ------->--------
970        # 1:    ------->--------
971        # value should be line0 or line1:
972        #       ------->--------
[6304]973        line0 = [P1, P3]
974        line1 = [P1, P3]
[5942]975        status, value = intersection(line0, line1)
976        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
977                               (str(status), str(value)))
[6158]978        self.failUnless(num.allclose(value, line0))
[5942]979
980        # line in same direction, same left point, same right point
981        # 0:    -------<--------
982        # 1:    -------<--------
983        # value should be line0 (or line1):
984        #       -------<--------
[6304]985        line0 = [P3, P1]
986        line1 = [P3, P1]
[5942]987        status, value = intersection(line0, line1)
988        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
989                               (str(status), str(value)))
[6158]990        self.failUnless(num.allclose(value, line0))
[5942]991
992        # line in opposite direction, same left point, same right point
993        # 0:    ------->--------
994        # 1:    -------<--------
995        # value should be line0:
996        #       ------->--------
[6304]997        line0 = [P1, P3]
998        line1 = [P3, P1]
[5942]999        status, value = intersection(line0, line1)
1000        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1001                               (str(status), str(value)))
[6158]1002        self.failUnless(num.allclose(value, line0))
[5942]1003
1004        # line in opposite direction, same left point, same right point
1005        # 0:    -------<--------
1006        # 1:    ------->--------
1007        # value should be line0:
1008        #       -------<--------
[6304]1009        line0 = [P3, P1]
1010        line1 = [P1, P3]
[5942]1011        status, value = intersection(line0, line1)
1012        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1013                               (str(status), str(value)))
[6158]1014        self.failUnless(num.allclose(value, line0))
[5942]1015
[6304]1016        # ----------------------------------------------------------------------
[5942]1017
1018        # line in same direction, same right point, line1 longer
1019        # 0:        ----->------
1020        # 1:    ------->--------
1021        # value should be line0:
1022        #           ----->------
[6304]1023        line0 = [P2, P4]
1024        line1 = [P1, P4]
[5942]1025        status, value = intersection(line0, line1)
1026        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1027                               (str(status), str(value)))
[6158]1028        self.failUnless(num.allclose(value, line0))
[5942]1029
1030        # line in same direction, same right point, line1 longer
1031        # 0:        -----<------
1032        # 1:    -------<--------
1033        # value should be line0:
1034        #           -----<------
[6304]1035        line0 = [P4, P2]
1036        line1 = [P4, P1]
[5942]1037        status, value = intersection(line0, line1)
1038        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1039                               (str(status), str(value)))
[6158]1040        self.failUnless(num.allclose(value, line0))
[5942]1041
1042        # line in opposite direction, same right point, line1 longer
1043        # 0:        ----->------
1044        # 1:    -------<--------
1045        # value should be line0:
1046        #           ----->------
[6304]1047        line0 = [P2, P4]
1048        line1 = [P4, P1]
[5942]1049        status, value = intersection(line0, line1)
1050        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1051                               (str(status), str(value)))
[6158]1052        self.failUnless(num.allclose(value, line0))
[5942]1053
1054        # line in opposite direction, same right point, line1 longer
1055        # 0:        -----<------
1056        # 1:    ------->--------
1057        # value should be line0:
1058        #           -----<------
[6304]1059        line0 = [P4, P2]
1060        line1 = [P1, P4]
[5942]1061        status, value = intersection(line0, line1)
1062        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1063                               (str(status), str(value)))
[6158]1064        self.failUnless(num.allclose(value, line0))
[5942]1065
[6304]1066        # ----------------------------------------------------------------------
[5942]1067
1068        # line in same direction, same left point, line0 longer
1069        # 0:    ------->--------
1070        # 1:    ----->------
1071        # value should be line1:
1072        #       ----->------
[6304]1073        line0 = [P1, P4]
1074        line1 = [P1, P3]
[5942]1075        status, value = intersection(line0, line1)
1076        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1077                               (str(status), str(value)))
[6158]1078        self.failUnless(num.allclose(value, line1))
[5942]1079
1080        # line in same direction, same left point, line0 longer
1081        # 0:    -------<--------
1082        # 1:    -----<------
1083        # value should be line1:
1084        #       -----<------
[6304]1085        line0 = [P4, P1]
1086        line1 = [P3, P1]
[5942]1087        status, value = intersection(line0, line1)
1088        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1089                               (str(status), str(value)))
[6158]1090        self.failUnless(num.allclose(value, line1))
[5942]1091
1092        # line in opposite direction, same left point, line0 longer
1093        # 0:    ------->--------
1094        # 1:    -----<------
1095        # value should be line1:
1096        #       -----<------
[6304]1097        line0 = [P1, P4]
1098        line1 = [P3, P1]
[5942]1099        status, value = intersection(line0, line1)
1100        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1101                               (str(status), str(value)))
[6158]1102        self.failUnless(num.allclose(value, line1))
[5942]1103
1104        # line in opposite direction, same left point, line0 longer
1105        # 0:    -------<--------
1106        # 1:    ----->------
1107        # value should be line1:
1108        #       ----->------
[6304]1109        line0 = [P4, P1]
1110        line1 = [P1, P3]
[5942]1111        status, value = intersection(line0, line1)
1112        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1113                               (str(status), str(value)))
[6158]1114        self.failUnless(num.allclose(value, line1))
[5942]1115
[6304]1116        # ----------------------------------------------------------------------
[5942]1117
1118        # line in same direction, same right point, line0 longer
1119        # 0:    ------->--------
1120        # 1:        ----->------
1121        # value should be line1:
1122        #           ----->------
[6304]1123        line0 = [P1, P4]
1124        line1 = [P2, P4]
[5942]1125        status, value = intersection(line0, line1)
1126        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1127                               (str(status), str(value)))
[6158]1128        self.failUnless(num.allclose(value, line1))
[5942]1129
1130        # line in same direction, same right point, line0 longer
1131        # 0:    -------<--------
1132        # 1:        -----<------
1133        # value should be line1:
1134        #           -----<------
[6304]1135        line0 = [P4, P1]
1136        line1 = [P4, P2]
[5942]1137        status, value = intersection(line0, line1)
1138        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1139                               (str(status), str(value)))
[6158]1140        self.failUnless(num.allclose(value, line1))
[5942]1141
1142        # line in opposite direction, same right point, line0 longer
1143        # 0:    ------->--------
1144        # 1:        -----<------
1145        # value should be line1:
1146        #           -----<------
[6304]1147        line0 = [P1, P4]
1148        line1 = [P4, P2]
[5942]1149        status, value = intersection(line0, line1)
1150        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1151                               (str(status), str(value)))
[6158]1152        self.failUnless(num.allclose(value, line1))
[5942]1153
1154        # line in opposite direction, same right point, line0 longer
1155        # 0:    -------<--------
1156        # 1:        ----->------
1157        # value should be line1:
1158        #           ----->------
[6304]1159        line0 = [P4, P1]
1160        line1 = [P2, P4]
[5942]1161        status, value = intersection(line0, line1)
1162        self.failIf(status!=2, 'Expected status 2, got status=%s, value=%s' %
1163                               (str(status), str(value)))
[6158]1164        self.failUnless(num.allclose(value, line1))
[5942]1165
[6304]1166
[5942]1167    def test_intersection_bug_20081110_TR(self):
[5933]1168        """test_intersection_bug_20081110(self)
1169
[5942]1170        Test all cases in top-right quadrant
[5933]1171        """
1172
[5942]1173        # define 4 collinear points in top-right quadrant
[5933]1174        #    P1---P2---P3---P4
[5942]1175        P1 = [1.0, 1.0]
1176        P2 = [2.0, 2.0]
1177        P3 = [3.0, 3.0]
1178        P4 = [4.0, 4.0]
[6304]1179
[5942]1180        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
1181        P1 = [1.0, 1.0+1.0e-9]
[6304]1182        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1183        P1 = [1.0, 1.0]
1184        P2 = [2.0, 2.0+1.0e-9]
[6304]1185        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1186        P2 = [2.0, 2.0]
1187        P3 = [3.0, 3.0+1.0e-9]
[6304]1188        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1189        P3 = [3.0, 3.0]
1190        P4 = [4.0, 4.0+1.0e-9]
[6304]1191        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1192
[5942]1193    def test_intersection_bug_20081110_TL(self):
1194        """test_intersection_bug_20081110(self)
[5933]1195
[5942]1196        Test all cases in top-left quadrant
1197        """
1198
1199        # define 4 collinear points in top-left quadrant
1200        #    P1---P2---P3---P4
1201        P1 = [-1.0, 1.0]
1202        P2 = [-2.0, 2.0]
1203        P3 = [-3.0, 3.0]
1204        P4 = [-4.0, 4.0]
[6304]1205
[5942]1206        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
1207        P1 = [-1.0, 1.0+1.0e-9]
[6304]1208        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1209        P1 = [-1.0, 1.0]
1210        P2 = [-2.0, 2.0+1.0e-9]
[6304]1211        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1212        P2 = [-2.0, 2.0]
1213        P3 = [-3.0, 3.0+1.0e-9]
[6304]1214        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1215        P3 = [-3.0, 3.0]
1216        P4 = [-4.0, 4.0+1.0e-9]
[6304]1217        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1218
1219    def test_intersection_bug_20081110_BL(self):
[5933]1220        """test_intersection_bug_20081110(self)
1221
[5942]1222        Test all cases in bottom-left quadrant
[5933]1223        """
1224
[5942]1225        # define 4 collinear points in bottom-left quadrant
[5933]1226        #    P1---P2---P3---P4
[5942]1227        P1 = [-1.0, -1.0]
1228        P2 = [-2.0, -2.0]
1229        P3 = [-3.0, -3.0]
1230        P4 = [-4.0, -4.0]
[6304]1231
[5942]1232        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
1233        P1 = [-1.0, -1.0+1.0e-9]
[6304]1234        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1235        P1 = [-1.0, -1.0]
1236        P2 = [-2.0, -2.0+1.0e-9]
[6304]1237        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1238        P2 = [-2.0, -2.0]
1239        P3 = [-3.0, -3.0+1.0e-9]
[6304]1240        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1241        P3 = [-3.0, -3.0]
1242        P4 = [-4.0, -4.0+1.0e-9]
[6304]1243        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1244
[5942]1245    def test_intersection_bug_20081110_BR(self):
[5933]1246        """test_intersection_bug_20081110(self)
1247
[5942]1248        Test all cases in bottom-right quadrant
[5933]1249        """
1250
[5942]1251        # define 4 collinear points in bottom-right quadrant
[5933]1252        #    P1---P2---P3---P4
[5942]1253        P1 = [1.0, -1.0]
1254        P2 = [2.0, -2.0]
1255        P3 = [3.0, -3.0]
1256        P4 = [4.0, -4.0]
[6304]1257
[5942]1258        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
1259        P1 = [1.0, -1.0+1.0e-9]
[6304]1260        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1261        P1 = [1.0, -1.0]
1262        P2 = [2.0, -2.0+1.0e-9]
[6304]1263        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1264        P2 = [2.0, -2.0]
1265        P3 = [3.0, -3.0+1.0e-9]
[6304]1266        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5942]1267        P3 = [3.0, -3.0]
1268        P4 = [4.0, -4.0+1.0e-9]
[6304]1269        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1270
[5942]1271    def test_intersection_bug_20081110_TR_TL(self):
[5933]1272        """test_intersection_bug_20081110(self)
1273
[5942]1274        Test all cases in top-right & top-left quadrant
[5933]1275        """
1276
[5942]1277        # define 4 collinear points, 1 in TL, 3 in TR
[6304]1278        #    P1-+-P2---P3---P4
[5942]1279        P1 = [-3.0, 1.0]
1280        P2 = [ 1.0, 5.0]
1281        P3 = [ 2.0, 6.0]
1282        P4 = [ 3.0, 7.0]
1283        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1284
[5942]1285        # define 4 collinear points, 2 in TL, 2 in TR
[6304]1286        #    P1---P2-+-P3---P4
[5942]1287        P1 = [-3.0, 1.0]
1288        P2 = [-2.0, 2.0]
1289        P3 = [ 2.0, 6.0]
1290        P4 = [ 3.0, 7.0]
1291        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1292
[6304]1293        # define 4 collinear points, 3 in TL, 1 in TR
1294        #    P1---P2---P3-+-P4
[5942]1295        P1 = [-3.0, 1.0]
1296        P2 = [-2.0, 2.0]
1297        P3 = [-1.0, 3.0]
1298        P4 = [ 3.0, 7.0]
1299        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1300
[5942]1301    def test_intersection_bug_20081110_TR_BL(self):
[5933]1302        """test_intersection_bug_20081110(self)
1303
[5942]1304        Test all cases in top-right & bottom-left quadrant
[5933]1305        """
1306
[5942]1307        # define 4 collinear points, 1 in BL, 3 in TR
[6304]1308        #    P1-+-P2---P3---P4
[5942]1309        P1 = [-4.0, -3.0]
1310        P2 = [ 1.0,  2.0]
1311        P3 = [ 2.0,  3.0]
1312        P4 = [ 3.0,  4.0]
1313        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1314
[5942]1315        # define 4 collinear points, 2 in TL, 2 in TR
[6304]1316        #    P1---P2-+-P3---P4
[5942]1317        P1 = [-4.0, -3.0]
1318        P2 = [-3.0, -2.0]
1319        P3 = [ 2.0,  3.0]
1320        P4 = [ 3.0,  4.0]
1321        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1322
[5942]1323        # define 4 collinear points, 3 in TL, 1 in TR
[6304]1324        #    P1---P2---P3-+-P4
[5942]1325        P1 = [-4.0, -3.0]
1326        P2 = [-3.0, -2.0]
1327        P3 = [-2.0, -1.0]
1328        P4 = [ 3.0,  4.0]
1329        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5933]1330
[5942]1331    def test_intersection_bug_20081110_TR_BR(self):
1332        """test_intersection_bug_20081110(self)
[5939]1333
[5942]1334        Test all cases in top-right & bottom-right quadrant
[5939]1335        """
1336
[5942]1337        # define 4 collinear points, 1 in BR, 3 in TR
[6304]1338        #    P1-+-P2---P3---P4
[5942]1339        P1 = [ 1.0, -3.0]
1340        P2 = [ 5.0,  1.0]
1341        P3 = [ 6.0,  2.0]
1342        P4 = [ 7.0,  3.0]
1343        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5939]1344
[5942]1345        # define 4 collinear points, 2 in BR, 2 in TR
[6304]1346        #    P1---P2-+-P3---P4
[5942]1347        P1 = [ 1.0, -3.0]
1348        P2 = [ 2.0, -2.0]
1349        P3 = [ 6.0,  2.0]
1350        P4 = [ 7.0,  3.0]
1351        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5939]1352
[5942]1353        # define 4 collinear points, 3 in BR, 1 in TR
[6304]1354        #    P1---P2---P3-+-P4
[5942]1355        P1 = [ 1.0, -3.0]
1356        P2 = [ 2.0, -2.0]
1357        P3 = [ 3.0, -1.0]
1358        P4 = [ 7.0,  3.0]
1359        self.helper_test_parallel_intersection_code(P1, P2, P3, P4)
[5939]1360
[5940]1361
[5897]1362    def test_intersection_direction_invariance(self):
[6304]1363        """This runs through a number of examples and checks that
1364        direction of lines don't matter.
[5897]1365        """
[6304]1366
[5897]1367        line0 = [[0,0], [100,100]]
1368
1369        common_end_point = [20, 150]
[6304]1370
[5897]1371        for i in range(100):
1372            x = 20 + i * 1.0/100
1373
1374            line1 = [[x,0], common_end_point]
1375            status, p1 = intersection(line0, line1)
1376            assert status == 1
1377
1378            # Swap direction of line1
[6304]1379            line1 = [common_end_point, [x,0]]
[5897]1380            status, p2 = intersection(line0, line1)
[6304]1381            assert status == 1
[5897]1382
[6689]1383            msg = ('Orientation of line should not matter.\n'
[6304]1384                   'However, segment [%f,%f], [%f, %f]' %
1385                   (x, 0, common_end_point[0], common_end_point[1]))
1386            msg += ' gave %s, \nbut when reversed we got %s' % (p1, p2)
[6158]1387            assert num.allclose(p1, p2), msg
[5897]1388
1389            # Swap order of lines
1390            status, p3 = intersection(line1, line0)
[6304]1391            assert status == 1
[5897]1392            msg = 'Order of lines gave different results'
[6158]1393            assert num.allclose(p1, p3), msg
[5897]1394
1395    def test_no_intersection(self):
1396        line0 = [[-1,1], [1,1]]
1397        line1 = [[0,-1], [0,0]]
1398
1399        status, value = intersection(line0, line1)
1400        assert status == 0
1401        assert value is None
1402
1403    def test_intersection_parallel(self):
1404        line0 = [[-1,1], [1,1]]
1405        line1 = [[-1,0], [5,0]]
1406
1407        status, value = intersection(line0, line1)
[6304]1408        assert status == 4
[5897]1409        assert value is None
1410
1411        line0 = [[0,0], [10,100]]
1412        line1 = [[-10,5], [0,105]]
1413
1414        status, value = intersection(line0, line1)
[6304]1415        assert status == 4
1416        assert value is None
[5897]1417
1418    def test_intersection_coincide(self):
[6304]1419        """Test what happens when two lines partly coincide"""
[5897]1420
1421        # Overlap 1
1422        line0 = [[0,0], [5,0]]
1423        line1 = [[-3,0], [3,0]]
1424
1425        status, value = intersection(line0, line1)
1426        assert status == 2
[6158]1427        assert num.allclose(value, [[0,0], [3,0]])
[5897]1428
1429        # Overlap 2
1430        line0 = [[-10,0], [5,0]]
1431        line1 = [[-3,0], [10,0]]
1432
1433        status, value = intersection(line0, line1)
1434        assert status == 2
[6304]1435        assert num.allclose(value, [[-3, 0], [5,0]])
[5897]1436
1437        # Inclusion 1
1438        line0 = [[0,0], [5,0]]
1439        line1 = [[2,0], [3,0]]
1440
1441        status, value = intersection(line0, line1)
[6304]1442        assert status == 2
[6158]1443        assert num.allclose(value, line1)
[5897]1444
1445        # Inclusion 2
1446        line0 = [[1,0], [5,0]]
1447        line1 = [[-10,0], [15,0]]
1448
1449        status, value = intersection(line0, line1)
[6304]1450        assert status == 2
1451        assert num.allclose(value, line0)
[5897]1452
1453        # Exclusion (no intersection)
1454        line0 = [[-10,0], [1,0]]
1455        line1 = [[3,0], [15,0]]
1456
1457        status, value = intersection(line0, line1)
[6304]1458        assert status == 3
[5897]1459        assert value is None
1460
1461        # Try examples with some slope (y=2*x+5)
1462
1463        # Overlap
1464        line0 = [[0,5], [7,19]]
1465        line1 = [[1,7], [10,25]]
1466        status, value = intersection(line0, line1)
[6304]1467        assert status == 2
[6158]1468        assert num.allclose(value, [[1, 7], [7, 19]])
[5897]1469
1470        status, value = intersection(line1, line0)
1471        assert status == 2
[6158]1472        assert num.allclose(value, [[1, 7], [7, 19]])
[5897]1473
1474        # Swap direction
1475        line0 = [[7,19], [0,5]]
1476        line1 = [[1,7], [10,25]]
1477        status, value = intersection(line0, line1)
1478        assert status == 2
[6158]1479        assert num.allclose(value, [[7, 19], [1, 7]])
[5897]1480
1481        line0 = [[0,5], [7,19]]
1482        line1 = [[10,25], [1,7]]
1483        status, value = intersection(line0, line1)
1484        assert status == 2
[6304]1485        assert num.allclose(value, [[1, 7], [7, 19]])
[5897]1486
1487        # Inclusion
1488        line0 = [[1,7], [7,19]]
1489        line1 = [[0,5], [10,25]]
1490        status, value = intersection(line0, line1)
[6304]1491        assert status == 2
1492        assert num.allclose(value, [[1,7], [7, 19]])
[5897]1493
1494        line0 = [[0,5], [10,25]]
1495        line1 = [[1,7], [7,19]]
1496        status, value = intersection(line0, line1)
[6304]1497        assert status == 2
[6158]1498        assert num.allclose(value, [[1,7], [7, 19]])
[5897]1499
1500        line0 = [[0,5], [10,25]]
1501        line1 = [[7,19], [1,7]]
1502        status, value = intersection(line0, line1)
[6304]1503        assert status == 2
1504        assert num.allclose(value, [[7, 19], [1, 7]])
[5897]1505
[6304]1506
1507    def zzztest_inside_polygon_main(self):
1508        # FIXME (Ole): Why is this disabled?
[5897]1509        print "inside",inside
1510        print "outside",outside
1511
[6304]1512        assert not inside_polygon((0.5, 1.5), polygon)
1513        assert not inside_polygon((0.5, -0.5), polygon)
1514        assert not inside_polygon((-0.5, 0.5), polygon)
1515        assert not inside_polygon((1.5, 0.5), polygon)
[5897]1516
[6304]1517        # Try point on borders
1518        assert inside_polygon((1., 0.5), polygon, closed=True)
1519        assert inside_polygon((0.5, 1), polygon, closed=True)
1520        assert inside_polygon((0., 0.5), polygon, closed=True)
1521        assert inside_polygon((0.5, 0.), polygon, closed=True)
[5897]1522
[6304]1523        assert not inside_polygon((0.5, 1), polygon, closed=False)
1524        assert not inside_polygon((0., 0.5), polygon, closed=False)
1525        assert not inside_polygon((0.5, 0.), polygon, closed=False)
1526        assert not inside_polygon((1., 0.5), polygon, closed=False)
[5897]1527
[6304]1528        # From real example (that failed)
1529        polygon = [[20,20], [40,20], [40,40], [20,40]]
1530        points = [[40, 50]]
1531        res = inside_polygon(points, polygon)
1532        assert len(res) == 0
[5897]1533
[6304]1534        polygon = [[20,20], [40,20], [40,40], [20,40]]
1535        points = [[25, 25], [30, 20], [40, 50], [90, 20], [40, 90]]
1536        res = inside_polygon(points, polygon)
1537        assert len(res) == 2
1538        assert num.allclose(res, [0,1])
[5897]1539
1540    def test_polygon_area(self):
[6304]1541        # Simplest case: Polygon is the unit square
[5897]1542        polygon = [[0,0], [1,0], [1,1], [0,1]]
[6304]1543        assert polygon_area(polygon) == 1
[5897]1544
[6304]1545        # Simple case: Polygon is a rectangle
[5897]1546        polygon = [[0,0], [1,0], [1,4], [0,4]]
[6304]1547        assert polygon_area(polygon) == 4
[5897]1548
[6304]1549        # Simple case: Polygon is a unit triangle
[5897]1550        polygon = [[0,0], [1,0], [0,1]]
[6304]1551        assert polygon_area(polygon) == 0.5
[5897]1552
[6304]1553        # Simple case: Polygon is a diamond
[5897]1554        polygon = [[0,0], [1,1], [2,0], [1, -1]]
[6304]1555        assert polygon_area(polygon) == 2.0
1556
[6000]1557        # Complex case where numerical errors might occur
1558        polygon = [[314037.58727982, 6224952.2960092],
[6304]1559                   [314038.58727982, 6224952.2960092],
[6000]1560                   [314038.58727982, 6224953.2960092],
1561                   [314037.58727982, 6224953.2960092]]
[6304]1562        assert polygon_area(polygon) == 1.0
[5897]1563
1564    def test_poly_xy(self):
[6304]1565        # Simplest case: Polygon is the unit square
[5897]1566        polygon = [[0,0], [1,0], [1,1], [0,1]]
1567        x, y = poly_xy(polygon)
[6304]1568        assert len(x) == len(polygon)+1
1569        assert len(y) == len(polygon)+1
1570        assert x[0] == 0
1571        assert x[1] == 1
1572        assert x[2] == 1
1573        assert x[3] == 0
1574        assert y[0] == 0
1575        assert y[1] == 0
1576        assert y[2] == 1
1577        assert y[3] == 1
[5897]1578
[6304]1579    # Arbitrary polygon
[5897]1580        polygon = [[1,5], [1,1], [100,10], [1,10], [3,6]]
1581        x, y = poly_xy(polygon)
[6304]1582        assert len(x) == len(polygon)+1
1583        assert len(y) == len(polygon)+1
1584        assert x[0] == 1
1585        assert x[1] == 1
1586        assert x[2] == 100
1587        assert x[3] == 1
1588        assert x[4] == 3
1589        assert y[0] == 5
1590        assert y[1] == 1
1591        assert y[2] == 10
1592        assert y[3] == 10
1593        assert y[4] == 6
[5897]1594
[6304]1595    # Disabled
[5897]1596    def xtest_plot_polygons(self):
1597        import os
[6304]1598
1599        # Simplest case: Polygon is the unit square
[5897]1600        polygon1 = [[0,0], [1,0], [1,1], [0,1]]
1601        polygon2 = [[1,1], [2,1], [3,2], [2,2]]
[6304]1602        v = plot_polygons([polygon1, polygon2], 'test1')
1603        assert len(v) == 4
1604        assert v[0] == 0
1605        assert v[1] == 3
1606        assert v[2] == 0
1607        assert v[3] == 2
[5897]1608
[6304]1609        # Another case
[5897]1610        polygon3 = [[1,5], [10,1], [100,10], [50,10], [3,6]]
[6304]1611        v = plot_polygons([polygon2,polygon3], 'test2')
1612        assert len(v) == 4
1613        assert v[0] == 1
1614        assert v[1] == 100
1615        assert v[2] == 1
1616        assert v[3] == 10
[5897]1617
[6304]1618        os.remove('test1.png')
1619        os.remove('test2.png')
[5897]1620
1621    def test_inside_polygon_geospatial(self):
[6441]1622        #Simplest case: Polygon is the unit square
[5897]1623        polygon_absolute = [[0,0], [1,0], [1,1], [0,1]]
[6304]1624        poly_geo_ref = Geo_reference(57, 100, 100)
1625        polygon = poly_geo_ref.change_points_geo_ref(polygon_absolute)
1626        poly_spatial = Geospatial_data(polygon, geo_reference=poly_geo_ref)
[6441]1627
1628        points_absolute = (0.5, 0.5)
[6304]1629        points_geo_ref = Geo_reference(57, 78, -56)
[6441]1630        points = points_geo_ref.change_points_geo_ref(points_absolute)
1631        points_spatial = Geospatial_data(points, geo_reference=points_geo_ref)
[5897]1632
[6441]1633        assert is_inside_polygon(points_absolute, polygon_absolute)
1634        assert is_inside_polygon(ensure_numeric(points_absolute),
1635                                 ensure_numeric(polygon_absolute))
1636        assert is_inside_polygon(points_absolute, poly_spatial)
1637        assert is_inside_polygon(points_spatial, poly_spatial)
1638        assert is_inside_polygon(points_spatial, polygon_absolute)
[6360]1639
[6441]1640        assert is_inside_polygon(points_absolute, polygon_absolute)
[6360]1641
[5897]1642    def NOtest_decimate_polygon(self):
1643        polygon = [[0,0], [10,10], [15,5], [20, 10],
1644                   [25,0], [30,10], [40,-10], [35, -5]]
1645
1646        dpoly = decimate_polygon(polygon, factor=2)
1647
1648        print dpoly
[6304]1649
[5897]1650        assert len(dpoly)*2==len(polygon)
1651
1652        minx = maxx = polygon[0][0]
1653        miny = maxy = polygon[0][1]
1654        for point in polygon[1:]:
1655            x, y = point
[6304]1656
[5897]1657            if x < minx: minx = x
1658            if x > maxx: maxx = x
1659            if y < miny: miny = y
1660            if y > maxy: maxy = y
1661
1662        assert [minx, miny] in polygon
1663        print minx, maxy
1664        assert [minx, maxy] in polygon
1665        assert [maxx, miny] in polygon
[6304]1666        assert [maxx, maxy] in polygon
[5897]1667
[6189]1668    def test_interpolate_polyline(self):
1669        """test_interpolate_polyline(self):
[6304]1670
1671        This test is added under the assumption that the function
1672        interpolate_polyline implemented by John Jakeman works.
1673        It has been exercised somewhat by tests of sts boundary,
1674        but never before separately.
[6189]1675        """
[6304]1676
[6189]1677        f = num.array([58.06150614, 58.06150614, 58.06150614])
1678        vertex_coordinates = num.array([[0., 0., ],
1679                                        [4.04092634, 1106.11074699],
1680                                        [8.08836552, 2212.16910609]])
1681        gauge_neighbour_id = [1, 2, -1]
1682        point_coordinates = num.array([[2.21870766e+03, 1.09802864e+03],
1683                                       [1.62739645e+03, 2.20626983e+03],
1684                                       [5.20084967e+02, 2.21030386e+03],
1685                                       [6.06464546e+00, 1.65913993e+03],
1686                                       [1.61934862e+03, -5.88143836e+00],
1687                                       [5.11996623e+02, -1.85956061e+00],
1688                                       [2.02046270e+00, 5.53055373e+02]])
[6304]1689
[6189]1690        z_ref = [0., 0., 0., 58.06150614, 0., 0., 58.06150614]
[6304]1691
1692        z = interpolate_polyline(f, vertex_coordinates,
1693                                 gauge_neighbour_id, point_coordinates)
[6189]1694        assert num.allclose(z, z_ref)
[6304]1695
[6189]1696        # Another f
1697        f = num.array([58.06150614, 158.06150614, 258.06150614])
[6304]1698        z_ref = [0., 0., 0., 208.06150645, 0., 0., 108.0615061]
1699        z = interpolate_polyline(f, vertex_coordinates,
1700                                 gauge_neighbour_id, point_coordinates)
1701        assert num.allclose(z, z_ref)
[6189]1702
1703        # Other and simpler numbers
[6304]1704        f = num.array([1, 5, 13])
[6189]1705        vertex_coordinates = num.array([[0., 0., ],
1706                                        [4., 4.],
[6304]1707                                        [8., 8.]])
[6189]1708        point_coordinates = num.array([[0.1, 0.1],
1709                                       [3.5, 3.5],
1710                                       [4.0, 4.0],
1711                                       [5.2, 5.2],
1712                                       [7.0, 7.0],
1713                                       [8.3, 8.3]])
1714        gauge_neighbour_id = [1, 2, -1]
[6304]1715
1716        z = interpolate_polyline(f, vertex_coordinates,
1717                                 gauge_neighbour_id, point_coordinates)
[6189]1718        z_ref = [1.1, 4.5, 5., 7.4, 11., 0.]
[6304]1719        assert num.allclose(z, z_ref)
1720
[6189]1721        # Test exception thrown for one point
[6304]1722        f = num.array([5])
1723        vertex_coordinates = num.array([[4., 4.]])
1724        try:
1725            z = interpolate_polyline(f, vertex_coordinates,
1726                                     gauge_neighbour_id, point_coordinates)
[6189]1727        except Exception:
1728            pass
1729        else:
1730            raise Exception, 'One point should have raised exception'
1731
1732        # More polyline nodes
[6304]1733        data = num.array([1, 5, 13, 12, 6, 29])
[6189]1734        polyline_nodes = num.array([[0., 0.],
1735                                    [4., 4.],
1736                                    [8., 8.],
1737                                    [10., 10.],
1738                                    [10., 5.],
1739                                    [10., 0.]])
1740        point_coordinates = num.array([[0.1, 0.1],
1741                                       [3.5, 3.5],
1742                                       [4.0, 4.0],
1743                                       [5.2, 5.2],
1744                                       [7.0, 7.0],
1745                                       [8.3, 8.3],
1746                                       [10., 10.],
1747                                       [10., 9.],
1748                                       [10., 7.1],
1749                                       [10., 4.3],
1750                                       [10., 1.0]])
1751        gauge_neighbour_id = [1, 2, 3, 4, 5, -1]
[6304]1752        z = interpolate_polyline(data, polyline_nodes,
1753                                 gauge_neighbour_id, point_coordinates)
[6189]1754        z_ref = [1.1, 4.5, 5., 7.4, 11., 12.85, 12., 10.8, 8.52, 9.22, 24.4]
[6304]1755        assert num.allclose(z, z_ref)
1756
[6410]1757
[6553]1758    def test_is_inside_triangle_more(self):
[6410]1759
[6553]1760        res = is_inside_triangle([0.5, 0.5], [[ 0.5,  0. ],
1761                                              [ 0.5,  0.5],
1762                                              [ 0.,   0. ]])
1763        assert res is True
[6410]1764
[6553]1765        res = is_inside_triangle([0.59999999999999998, 0.29999999999999999],
1766                                 [[ 0.5,  0. ], [ 0.5, 0.5], [0., 0.]])
1767        assert res is False
[6410]1768
[6553]1769        res = is_inside_triangle([0.59999999999999998, 0.29999999999999999],
1770                                 [[1., 0.], [1., 0.5], [0.5, 0.]])
1771        assert res is False
[6410]1772
1773
[6553]1774        res = is_inside_triangle([0.59999999999999998, 0.29999999999999999],
1775                                 [[0.5, 0.5], [0.5, 0.], [1., 0.5]])
1776        assert res is True
[6410]1777
[6553]1778
1779        res = is_inside_triangle([0.10000000000000001, 0.20000000000000001],
1780                                 [[0.5, 0.], [0.5, 0.5], [0., 0.]])
1781        assert res is False
1782
1783
1784        res = is_inside_triangle([0.10000000000000001, 0.20000000000000001],
1785                                 [[0., 0.5], [0., 0.], [0.5, 0.5]])
1786        assert res is True
1787
1788        res = is_inside_triangle([0.69999999999999996, 0.69999999999999996],
1789                                 [[0.5, 0.], [0.5, 0.5], [0., 0.]])
1790        assert res is False
1791
1792        res = is_inside_triangle([0.59999999999999998, 0.29999999999999999],
1793                                 [[0.25, 0.5], [0.25, 0.25], [0.5, 0.5]])
1794        assert res is False
1795
1796
1797        res = is_inside_triangle([10, 3],
1798                                 [[0.1, 0.],
1799                                  [0.1, 0.08333333],
1800                                  [0., 0.]])
1801        assert res is False
1802
[6360]1803################################################################################
[6304]1804
[5897]1805if __name__ == "__main__":
[6360]1806    suite = unittest.makeSuite(Test_Polygon,'test')
[5897]1807    runner = unittest.TextTestRunner()
1808    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.