source: anuga_core/source/anuga/abstract_2d_finite_volumes/test_neighbour_mesh.py @ 7276

Last change on this file since 7276 was 7276, checked in by ole, 15 years ago

Merged numpy branch back into the trunk.

In ~/sandpit/anuga/anuga_core/source
svn merge -r 6246:HEAD ../../branches/numpy .

In ~/sandpit/anuga/anuga_validation
svn merge -r 6417:HEAD ../branches/numpy_anuga_validation .

In ~/sandpit/anuga/misc
svn merge -r 6809:HEAD ../branches/numpy_misc .

For all merges, I used numpy version where conflicts existed

The suites test_all.py (in source/anuga) and validate_all.py passed using Python2.5 with numpy on my Ubuntu Linux box.

File size: 54.0 KB
Line 
1#!/usr/bin/env python
2
3
4
5#FIXME: Seperate the tests for mesh and general_mesh
6
7#FIXME (Ole): Maxe this test independent of anything that inherits from General_mesh (namely shallow_water)
8
9import unittest
10from math import sqrt
11
12from neighbour_mesh import *
13from mesh_factory import rectangular
14from mesh_factory import rectangular_periodic
15from anuga.config import epsilon
16
17from anuga.coordinate_transforms.geo_reference import Geo_reference
18from anuga.utilities.polygon import is_inside_polygon
19from anuga.utilities.numerical_tools import ensure_numeric
20
21import numpy as num
22
23
24def distance(x, y):
25    return sqrt(num.sum((num.array(x)-num.array(y))**2))
26
27class Test_Mesh(unittest.TestCase):
28    def setUp(self):
29        pass
30
31    def tearDown(self):
32        pass
33
34    def test_triangle_inputs(self):
35        points = [[0.0, 0.0], [4.0, 0.0], [0.0, 3.0]]
36        vertices = [0,1,2] #Wrong
37
38        try:
39            mesh = Mesh(points, vertices)
40        except:
41            pass
42        else:
43            msg = 'Should have raised exception'
44            raise msg
45
46
47    def test_basic_triangle(self):
48
49        a = [0.0, 0.0]
50        b = [4.0, 0.0]
51        c = [0.0, 3.0]
52
53        points = [a, b, c]
54        vertices = [[0,1,2]]
55        mesh = Mesh(points, vertices)
56
57        #Centroid
58        centroid = mesh.centroid_coordinates[0]
59        assert centroid[0] == 4.0/3
60        assert centroid[1] == 1.0
61
62        #Area
63        assert mesh.areas[0] == 6.0,\
64               'Area was %f, should have been 6.0' %mesh.areas[0]
65
66        #Normals
67        normals = mesh.get_normals()
68        assert num.allclose(normals[0, 0:2], [3.0/5, 4.0/5])
69        assert num.allclose(normals[0, 2:4], [-1.0, 0.0])
70        assert num.allclose(normals[0, 4:6], [0.0, -1.0])
71
72        assert num.allclose(mesh.get_normal(0,0), [3.0/5, 4.0/5])
73        assert num.allclose(mesh.get_normal(0,1), [-1.0, 0.0])
74        assert num.allclose(mesh.get_normal(0,2), [0.0, -1.0])
75
76        #Edge lengths
77        assert num.allclose(mesh.edgelengths[0], [5.0, 3.0, 4.0])
78
79
80        #Vertex coordinates
81        #V = mesh.get_vertex_coordinates()
82        #assert allclose(V[0], [0.0, 0.0, 4.0, 0.0, 0.0, 3.0])
83       
84
85        V = mesh.get_vertex_coordinates()
86        assert num.allclose(V, [ [0.0, 0.0],
87                             [4.0, 0.0],
88                             [0.0, 3.0] ])
89
90        V0 = mesh.get_vertex_coordinate(0, 0)
91        assert num.allclose(V0, [0.0, 0.0])
92
93        V1 = mesh.get_vertex_coordinate(0, 1)
94        assert num.allclose(V1, [4.0, 0.0])
95
96        V2 = mesh.get_vertex_coordinate(0, 2)
97        assert num.allclose(V2, [0.0, 3.0])
98
99
100        #General tests:
101
102        #Test that points are arranged in a counter clock wise order etc
103        mesh.check_integrity()
104
105
106        #Test that the centroid is located 2/3 of the way
107        #from each vertex to the midpoint of the opposite side
108
109        V = mesh.get_vertex_coordinates()
110        x0 = V[0, 0]; y0 = V[0, 1]
111        x1 = V[1, 0]; y1 = V[1, 1]
112        x2 = V[2, 0]; y2 = V[2, 1]
113        #x0 = V[0,0]
114        #y0 = V[0,1]
115        #x1 = V[0,2]
116        #y1 = V[0,3]
117        #x2 = V[0,4]
118        #y2 = V[0,5]
119
120        m0 = [(x1 + x2)/2, (y1 + y2)/2]
121        m1 = [(x0 + x2)/2, (y0 + y2)/2]
122        m2 = [(x1 + x0)/2, (y1 + y0)/2]
123
124        d0 = distance(centroid, [x0, y0])
125        d1 = distance(m0, [x0, y0])
126        assert d0 == 2*d1/3
127        #
128        d0 = distance(centroid, [x1, y1])
129        d1 = distance(m1, [x1, y1])
130        assert abs(d0 - 2*d1/3) < epsilon, '%e, %e' %(d0, 2*d1/3)
131
132        d0 = distance(centroid, [x2, y2])
133        d1 = distance(m2, [x2, y2])
134        assert abs(d0 - 2*d1/3) < epsilon, '%e, %e' %(d0, 2*d1/3)
135
136        #Radius
137        d0 = distance(centroid, m0)
138        assert d0 == 5.0/6
139
140        d1 = distance(centroid, m1)
141        assert d1 == sqrt(73.0/36)
142
143        d2 = distance(centroid, m2)
144        assert d2 == sqrt(13.0/9)
145
146        assert mesh.radii[0] == min(d0, d1, d2)
147        assert mesh.radii[0] == 5.0/6
148
149
150        #Let x be the centroid of triangle abc.
151        #Test that areas of the three triangles axc, cxb, and bxa are equal.
152        points = [a, b, c, centroid]
153        vertices = [[0,3,2], [2,3,1], [1,3,0]]
154        new_mesh = Mesh(points, vertices)
155
156        assert new_mesh.areas[0] == new_mesh.areas[1]
157        assert new_mesh.areas[1] == new_mesh.areas[2]
158        assert new_mesh.areas[1] == new_mesh.areas[2]
159
160        assert new_mesh.areas[1] == mesh.areas[0]/3
161
162
163
164    def test_general_triangle(self):
165        a = [2.0, 1.0]
166        b = [6.0, 2.0]
167        c = [1.0, 3.0]
168
169        points = [a, b, c]
170        vertices = [[0,1,2]]
171
172        mesh = Mesh(points, vertices)
173        centroid = mesh.centroid_coordinates[0]
174
175
176        #Test that the centroid is located 2/3 of the way
177        #from each vertex to the midpoint of the opposite side
178
179        V = mesh.get_vertex_coordinates()
180        x0 = V[0, 0]; y0 = V[0, 1]
181        x1 = V[1, 0]; y1 = V[1, 1]
182        x2 = V[2, 0]; y2 = V[2, 1]       
183
184        #x0 = V[0,0]
185        #y0 = V[0,1]
186        #x1 = V[0,2]
187        #y1 = V[0,3]
188        #x2 = V[0,4]
189        #y2 = V[0,5]
190
191        m0 = [(x1 + x2)/2, (y1 + y2)/2]
192        m1 = [(x0 + x2)/2, (y0 + y2)/2]
193        m2 = [(x1 + x0)/2, (y1 + y0)/2]
194
195        d0 = distance(centroid, [x0, y0])
196        d1 = distance(m0, [x0, y0])
197        assert abs(d0 - 2*d1/3) < epsilon, '%e, %e' %(d0, 2*d1/3)
198        #
199        d0 = distance(centroid, [x1, y1])
200        d1 = distance(m1, [x1, y1])
201        assert abs(d0 - 2*d1/3) < epsilon, '%e, %e' %(d0, 2*d1/3)
202
203        d0 = distance(centroid, [x2, y2])
204        d1 = distance(m2, [x2, y2])
205        assert abs(d0 - 2*d1/3) < epsilon, '%e, %e' %(d0, 2*d1/3)
206
207        #Radius
208        d0 = distance(centroid, m0)
209        d1 = distance(centroid, m1)
210        d2 = distance(centroid, m2)
211        assert mesh.radii[0] == min(d0, d1, d2)
212
213
214
215        #Let x be the centroid of triangle abc.
216        #Test that areas of the three triangles axc, cxb, and bxa are equal.
217
218        points = [a, b, c, centroid]
219        vertices = [[0,3,2], [2,3,1], [1,3,0]]
220        new_mesh = Mesh(points, vertices)
221
222        assert new_mesh.areas[0] == new_mesh.areas[1]
223        assert new_mesh.areas[1] == new_mesh.areas[2]
224        assert new_mesh.areas[1] == new_mesh.areas[2]
225
226        assert new_mesh.areas[1] == mesh.areas[0]/3
227
228
229        #Test that points are arranged in a counter clock wise order
230        mesh.check_integrity()
231
232    def test_inscribed_circle_equilateral(self):
233        """test that the radius is calculated correctly by mesh in the case of an equilateral triangle"""
234        a = [0.0, 0.0]
235        b = [2.0, 0.0]
236        c = [1.0, sqrt(3.0)]
237
238        points = [a, b, c]
239        vertices = [[0,1,2]]
240
241        mesh = Mesh(points, vertices,use_inscribed_circle=False)
242        assert num.allclose(mesh.radii[0],sqrt(3.0)/3),'Steve''s doesn''t work'
243
244        mesh = Mesh(points, vertices,use_inscribed_circle=True)
245        assert num.allclose(mesh.radii[0],sqrt(3.0)/3),'inscribed circle doesn''t work'
246
247    def test_inscribed_circle_rightangle_triangle(self):
248        """test that the radius is calculated correctly by mesh in the case of a right-angled triangle"""
249        a = [0.0, 0.0]
250        b = [4.0, 0.0]
251        c = [0.0, 3.0]
252
253        points = [a, b, c]
254        vertices = [[0,1,2]]
255
256        mesh = Mesh(points, vertices,use_inscribed_circle=False)
257        assert num.allclose(mesh.radii[0],5.0/6),'Steve''s doesn''t work'
258
259        mesh = Mesh(points, vertices,use_inscribed_circle=True)
260        assert num.allclose(mesh.radii[0],1.0),'inscribed circle doesn''t work'
261
262
263    def test_two_triangles(self):
264        a = [0.0, 0.0]
265        b = [0.0, 2.0]
266        c = [2.0,0.0]
267        e = [2.0, 2.0]
268        points = [a, b, c, e]
269        vertices = [ [1,0,2], [1,2,3] ]   #bac, bce
270        mesh = Mesh(points, vertices)
271
272        assert mesh.areas[0] == 2.0
273
274        assert num.allclose(mesh.centroid_coordinates[0], [2.0/3, 2.0/3])
275
276
277        #Test that points are arranged in a counter clock wise order
278        mesh.check_integrity()
279
280
281
282    def test_more_triangles(self):
283
284        a = [0.0, 0.0]
285        b = [0.0, 2.0]
286        c = [2.0, 0.0]
287        d = [0.0, 4.0]
288        e = [2.0, 2.0]
289        f = [4.0, 0.0]
290
291        points = [a, b, c, d, e, f]
292        #bac, bce, ecf, dbe, daf, dae
293        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
294        mesh = Mesh(points, vertices)
295
296        #Test that points are arranged in a counter clock wise order
297        mesh.check_integrity()
298
299        assert mesh.areas[0] == 2.0
300        assert mesh.areas[1] == 2.0
301        assert mesh.areas[2] == 2.0
302        assert mesh.areas[3] == 2.0
303
304        assert mesh.edgelengths[1,0] == 2.0
305        assert mesh.edgelengths[1,1] == 2.0
306        assert mesh.edgelengths[1,2] == sqrt(8.0)
307
308        assert num.allclose(mesh.centroid_coordinates[0], [2.0/3, 2.0/3])
309        assert num.allclose(mesh.centroid_coordinates[1], [4.0/3, 4.0/3])
310        assert num.allclose(mesh.centroid_coordinates[2], [8.0/3, 2.0/3])
311        assert num.allclose(mesh.centroid_coordinates[3], [2.0/3, 8.0/3])
312
313    def test_mesh_and_neighbours(self):
314        a = [0.0, 0.0]
315        b = [0.0, 2.0]
316        c = [2.0,0.0]
317        d = [0.0, 4.0]
318        e = [2.0, 2.0]
319        f = [4.0,0.0]
320
321
322        points = [a, b, c, d, e, f]
323
324        #bac, bce, ecf, dbe
325        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
326        mesh = Mesh(points, vertices)
327
328        mesh.check_integrity()
329
330
331        T = mesh
332        tid = 0
333        assert T.number_of_boundaries[tid] == 2
334        assert T.neighbours[tid, 0] < 0  #Opposite point b (0,2)
335        assert T.neighbours[tid, 1] == 1 #Opposite point a (0,0)
336        assert T.neighbours[tid, 2] < 0  #Opposite point c (2,0)
337
338        tid = 1
339        assert T.number_of_boundaries[tid] == 0
340        assert T.neighbours[tid, 0] == 2  #Opposite point b (0,2)
341        assert T.neighbours[tid, 1] == 3  #Opposite point c (2,0)
342        assert T.neighbours[tid, 2] == 0  #Opposite point e (2,2)
343
344        tid = 2
345        assert T.number_of_boundaries[tid] == 2
346        assert T.neighbours[tid, 0] < 0   #Opposite point e (2,2)
347        assert T.neighbours[tid, 1] < 0   #Opposite point c (2,0)
348        assert T.neighbours[tid, 2] == 1  #Opposite point f (4,0)
349
350        tid = 3
351        assert T.number_of_boundaries[tid] == 2
352        assert T.neighbours[tid, 0] == 1  #Opposite point d (0,4)
353        assert T.neighbours[tid, 1] < 0   #Opposite point b (0,3)
354        assert T.neighbours[tid, 2] < 0   #Opposite point e (2,2)
355
356        #Neighbouring edges
357        tid = 0
358        assert T.neighbour_edges[tid, 0] < 0  #Opposite point b (0,2)
359        assert T.neighbour_edges[tid, 1] == 2 #Opposite point a (0,0)
360        assert T.neighbour_edges[tid, 2] < 0  #Opposite point c (2,0)
361
362        tid = 1
363        assert T.neighbour_edges[tid, 0] == 2 #Opposite point b (0,2)
364        assert T.neighbour_edges[tid, 1] == 0 #Opposite point c (2,0)
365        assert T.neighbour_edges[tid, 2] == 1 #Opposite point e (2,2)
366
367        tid = 2
368        assert T.neighbour_edges[tid, 0] < 0  #Opposite point e (2,2)
369        assert T.neighbour_edges[tid, 1] < 0  #Opposite point c (2,0)
370        assert T.neighbour_edges[tid, 2] == 0 #Opposite point f (4,0)
371
372        tid = 3
373        assert T.neighbour_edges[tid, 0] == 1 #Opposite point d (0,4)
374        assert T.neighbour_edges[tid, 1] < 0  #Opposite point b (0,3)
375        assert T.neighbour_edges[tid, 2] < 0  #Opposite point e (2,2)
376
377
378    def test_build_neighbour_structure_duplicates(self):
379        p0 = [-66.0, 14.0]
380        p1 = [14.0, -66.0]
381        p2 = [14.0, 14.0]
382        p3 = [60.0, 20.0]
383        p4 = [10.0, 60.0]
384        p5 = [60.0, 60.0]
385
386        points = [p0, p1, p2, p3, p4, p5]
387        triangles = [ [0, 1, 2],
388                      [3, 2, 1],
389                      [0, 2, 4],
390                      [0, 2, 4],
391                      [4, 2, 5],
392                      [5, 2, 3]]
393        try:
394            mesh = Mesh(points, triangles)
395        except:
396            pass
397        else:
398            raise "triangle edge duplicates not caught"
399
400
401    def test_rectangular_mesh_basic(self):
402        M=1
403        N=1
404
405        points, vertices, boundary = rectangular(M, N)
406        mesh = Mesh(points, vertices, boundary)
407
408        #Test that points are arranged in a counter clock wise order
409        mesh.check_integrity()
410
411        M=2
412        N=2
413        points, vertices, boundary = rectangular(M, N)
414        mesh = Mesh(points, vertices, boundary)
415
416        #Test that points are arranged in a counter clock wise order
417        mesh.check_integrity()
418
419        #assert mesh.boundary[(7,1)] == 2 # top
420        assert mesh.boundary[(7,1)] == 'top' # top
421        assert mesh.boundary[(3,1)] == 'top' # top
422
423
424
425
426
427
428    def test_boundary_tags(self):
429
430
431        points, vertices, boundary = rectangular(4, 4)
432        mesh = Mesh(points, vertices, boundary)
433
434
435        #Test that points are arranged in a counter clock wise order
436        mesh.check_integrity()
437
438        #print mesh.get_boundary_tags()
439        #print mesh.boundary
440
441        for k in [1, 3, 5, 7]:
442            assert mesh.boundary[(k,2)] == 'left'
443
444        for k in [24, 26, 28, 30]:
445            assert mesh.boundary[(k,2)] == 'right'
446
447        for k in [7, 15, 23, 31]:
448            assert mesh.boundary[(k,1)] == 'top'
449        for k in [0, 8, 16, 24]:
450            assert mesh.boundary[(k,1)] == 'bottom'
451
452
453
454    def test_rectangular_mesh(self):
455        M=4
456        N=16
457        len1 = 100.0
458        len2 = 17.0
459
460        points, vertices, boundary = rectangular(M, N, len1, len2)
461        mesh = Mesh(points, vertices, boundary)
462
463        assert len(mesh) == 2*M*N
464
465        for i in range(len(mesh)):
466            assert mesh.areas[i] == len1*len2/(2*M*N)
467
468            hypo = sqrt((len1/M)**2 + (len2/N)**2) #hypothenuse
469            assert mesh.edgelengths[i, 0] == hypo
470            assert mesh.edgelengths[i, 1] == len1/M #x direction
471            assert mesh.edgelengths[i, 2] == len2/N #y direction
472
473        #Test that points are arranged in a counter clock wise order
474        mesh.check_integrity()
475
476
477    def test_rectangular_mesh2(self):
478        #Check that integers don't cause trouble
479        N = 16
480
481        points, vertices, boundary = rectangular(2*N, N, len1=10, len2=10)
482        mesh = Mesh(points, vertices, boundary)
483
484
485    def test_surrogate_neighbours(self):
486        a = [0.0, 0.0]
487        b = [0.0, 2.0]
488        c = [2.0,0.0]
489        d = [0.0, 4.0]
490        e = [2.0, 2.0]
491        f = [4.0,0.0]
492
493        points = [a, b, c, d, e, f]
494
495        #bac, bce, ecf, dbe
496        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
497        mesh = Mesh(points, vertices)
498        mesh.check_integrity()
499
500
501        T = mesh
502        tid = 0
503        assert T.number_of_boundaries[tid] == 2
504        assert T.surrogate_neighbours[tid, 0] == tid
505        assert T.surrogate_neighbours[tid, 1] == 1
506        assert T.surrogate_neighbours[tid, 2] == tid
507
508        tid = 1
509        assert T.number_of_boundaries[tid] == 0
510        assert T.surrogate_neighbours[tid, 0] == 2
511        assert T.surrogate_neighbours[tid, 1] == 3
512        assert T.surrogate_neighbours[tid, 2] == 0
513
514        tid = 2
515        assert T.number_of_boundaries[tid] == 2
516        assert T.surrogate_neighbours[tid, 0] == tid
517        assert T.surrogate_neighbours[tid, 1] == tid
518        assert T.surrogate_neighbours[tid, 2] == 1
519
520        tid = 3
521        assert T.number_of_boundaries[tid] == 2
522        assert T.surrogate_neighbours[tid, 0] == 1
523        assert T.surrogate_neighbours[tid, 1] == tid
524        assert T.surrogate_neighbours[tid, 2] == tid
525
526
527    def test_boundary_inputs(self):
528        a = [0.0, 0.0]
529        b = [0.0, 2.0]
530        c = [2.0,0.0]
531        d = [0.0, 4.0]
532        e = [2.0, 2.0]
533        f = [4.0,0.0]
534
535        points = [a, b, c, d, e, f]
536
537        #bac, bce, ecf, dbe
538        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
539
540        boundary = { (0, 0): 'First',
541                     (0, 2): 'Second',
542                     (2, 0): 'Third',
543                     (2, 1): 'Fourth',
544                     (3, 1): 'Fifth',
545                     (3, 2): 'Sixth'}
546
547
548        mesh = Mesh(points, vertices, boundary)
549        mesh.check_integrity()
550
551
552        #Check enumeration
553        #for k, (vol_id, edge_id) in enumerate(mesh.boundary_segments):
554        #    b = -k-1
555        #    assert mesh.neighbours[vol_id, edge_id] == b
556
557
558
559    def test_boundary_inputs_using_one_default(self):
560        a = [0.0, 0.0]
561        b = [0.0, 2.0]
562        c = [2.0,0.0]
563        d = [0.0, 4.0]
564        e = [2.0, 2.0]
565        f = [4.0,0.0]
566
567        points = [a, b, c, d, e, f]
568
569        #bac, bce, ecf, dbe
570        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
571
572        boundary = { (0, 0): 'First',
573                     (0, 2): 'Second',
574                     (2, 0): 'Third',
575                     (2, 1): 'Fourth',
576                     #(3, 1): 'Fifth',  #Skip this
577                     (3, 2): 'Sixth'}
578
579
580        mesh = Mesh(points, vertices, boundary)
581        mesh.check_integrity()
582
583        from anuga.config import default_boundary_tag
584        assert mesh.boundary[ (3, 1) ] == default_boundary_tag
585
586
587        #Check enumeration
588        #for k, (vol_id, edge_id) in enumerate(mesh.boundary_segments):
589        #    b = -k-1
590        #    assert mesh.neighbours[vol_id, edge_id] == b
591
592    def test_boundary_inputs_using_all_defaults(self):
593        a = [0.0, 0.0]
594        b = [0.0, 2.0]
595        c = [2.0,0.0]
596        d = [0.0, 4.0]
597        e = [2.0, 2.0]
598        f = [4.0,0.0]
599
600        points = [a, b, c, d, e, f]
601
602        #bac, bce, ecf, dbe
603        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
604
605        boundary = { (0, 0): 'First',
606                     (0, 2): 'Second',
607                     (2, 0): 'Third',
608                     (2, 1): 'Fourth',
609                     #(3, 1): 'Fifth',  #Skip this
610                     (3, 2): 'Sixth'}
611
612
613        mesh = Mesh(points, vertices) #, boundary)
614        mesh.check_integrity()
615
616        from anuga.config import default_boundary_tag
617        assert mesh.boundary[ (0, 0) ] == default_boundary_tag
618        assert mesh.boundary[ (0, 2) ] == default_boundary_tag
619        assert mesh.boundary[ (2, 0) ] == default_boundary_tag
620        assert mesh.boundary[ (2, 1) ] == default_boundary_tag
621        assert mesh.boundary[ (3, 1) ] == default_boundary_tag
622        assert mesh.boundary[ (3, 2) ] == default_boundary_tag
623
624
625        #Check enumeration
626        #for k, (vol_id, edge_id) in enumerate(mesh.boundary_segments):
627        #    b = -k-1
628        #    assert mesh.neighbours[vol_id, edge_id] == b
629
630
631
632
633
634
635    def test_inputs(self):
636        a = [0.0, 0.0]
637        b = [0.0, 2.0]
638        c = [2.0,0.0]
639        d = [0.0, 4.0]
640        e = [2.0, 2.0]
641        f = [4.0,0.0]
642
643        points = [a, b, c, d, e, f]
644
645        #bac, bce, ecf, dbe
646        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4] ]
647
648        #Too few points
649        try:
650            mesh = Mesh([points[0]], vertices)
651        except AssertionError:
652            pass
653        else:
654            raise 'Should have raised an exception'
655
656        #Too few points - 1 element
657        try:
658            mesh = Mesh([points[0]], [vertices[0]])
659        except AssertionError:
660            pass
661        else:
662            raise 'Should have raised an exception'
663
664        #Wrong dimension of vertices
665        try:
666            mesh = Mesh(points, vertices[0])
667        except AssertionError:
668            pass
669        else:
670            raise 'Should have raised an exception'
671
672        #Unsubscriptable coordinates object raises exception
673        try:
674            mesh = Mesh(points[0], [vertices[0]])
675        except AssertionError:
676            pass
677        else:
678            raise 'Should have raised an exception'
679
680        #FIXME: This has been commented out pending a decision
681        #whether to allow partial boundary tags or not
682        #
683        #Not specifying all boundary tags
684        #try:
685        #    mesh = Mesh(points, vertices, {(3,0): 'x'})
686        #except AssertionError:
687        #    pass
688        #else:
689        #    raise 'Should have raised an exception'
690
691        #Specifying wrong non existing segment
692        try:
693            mesh = Mesh(points, vertices, {(5,0): 'x'})
694        except AssertionError:
695            pass
696        else:
697            raise 'Should have raised an exception'
698
699
700
701
702    def test_internal_boundaries(self):
703        """
704        get values based on triangle lists.
705        """
706        from mesh_factory import rectangular
707
708        #Create basic mesh
709        points, vertices, boundary = rectangular(1, 3)
710
711        # Add an internal boundary
712        boundary[(2,0)] = 'internal'
713        boundary[(1,0)] = 'internal'
714
715        #Create shallow water domain
716        domain = Mesh(points, vertices, boundary)
717        domain.build_tagged_elements_dictionary({'bottom':[0,1],
718                                                 'top':[4,5],
719                                                 'all':[0,1,2,3,4,5]})
720
721
722    def test_boundary_polygon(self):
723        from mesh_factory import rectangular
724        #from mesh import Mesh
725
726        #Create basic mesh
727        points, vertices, boundary = rectangular(2, 2)
728        mesh = Mesh(points, vertices, boundary)
729
730
731        P = mesh.get_boundary_polygon()
732
733        assert len(P) == 8
734        assert num.allclose(P, [[0.0, 0.0], [0.5, 0.0], [1.0, 0.0],
735                                [1.0, 0.5], [1.0, 1.0], [0.5, 1.0],
736                                [0.0, 1.0], [0.0, 0.5]])
737        for p in points:
738            #print p, P
739            assert is_inside_polygon(p, P)
740
741
742    def test_boundary_polygon_II(self):
743
744        #Points
745        a = [0.0, 0.0] #0
746        b = [0.0, 0.5] #1
747        c = [0.0, 1.0] #2
748        d = [0.5, 0.0] #3
749        e = [0.5, 0.5] #4
750        f = [1.0, 0.0] #5
751        g = [1.0, 0.5] #6
752        h = [1.0, 1.0] #7
753        i = [1.5, 0.5] #8
754
755        points = [a, b, c, d, e, f, g, h, i]
756
757        #dea, bae, bec, fgd,
758        #edg, ghe, gfi, gih
759        vertices = [ [3,4,0], [1,0,4], [1,4,2], [5,6,3],
760                     [4,3,6], [6,7,4], [6,5,8], [6,8,7]]
761
762        mesh = Mesh(points, vertices)
763
764        mesh.check_integrity()
765
766        P = mesh.get_boundary_polygon()
767
768        assert len(P) == 8
769        assert num.allclose(P, [a, d, f, i, h, e, c, b])
770
771        for p in points:
772            #print p, P
773            assert is_inside_polygon(p, P)
774
775
776    def test_boundary_polygon_III(self):
777        """Same as II but vertices ordered differently
778        """
779
780
781        #Points
782        a = [0.0, 0.0] #0
783        b = [0.0, 0.5] #1
784        c = [0.0, 1.0] #2
785        d = [0.5, 0.0] #3
786        e = [0.5, 0.5] #4
787        f = [1.0, 0.0] #5
788        g = [1.0, 0.5] #6
789        h = [1.0, 1.0] #7
790        i = [1.5, 0.5] #8
791
792        points = [a, b, c, d, e, f, g, h, i]
793
794        #edg, ghe, gfi, gih
795        #dea, bae, bec, fgd,
796        vertices = [[4,3,6], [6,7,4], [6,5,8], [6,8,7],
797                    [3,4,0], [1,0,4], [1,4,2], [5,6,3]]
798
799
800        mesh = Mesh(points, vertices)
801        mesh.check_integrity()
802
803
804        P = mesh.get_boundary_polygon()
805
806        assert len(P) == 8
807        assert num.allclose(P, [a, d, f, i, h, e, c, b])
808
809        for p in points:
810            assert is_inside_polygon(p, P)
811
812           
813    def test_boundary_polygon_IIIa(self):
814        """test_boundary_polygon_IIIa - Check pathological situation where
815        one triangle has no neighbours. This may be the case if a mesh
816        is partitioned using pymetis.
817        """
818
819
820        #Points
821        a = [0.0, 0.0] #0
822        b = [0.0, 0.5] #1
823        c = [0.0, 1.0] #2
824        d = [0.5, 0.0] #3
825        e = [0.5, 0.5] #4
826        f = [1.0, 0.0] #5
827        g = [1.0, 0.5] #6
828        h = [1.0, 1.0] #7
829       
830        # Add pathological triangle with no neighbours to an otherwise
831        # trivial mesh
832       
833        points = [a, b, c, d, e, f, g, h]
834
835        #cbe, aeb, dea, fed, ghe (pathological triangle)
836        vertices = [[2,1,4], [0,4,1], [3,4,0], [5,4,3],
837                    [6,7,4]]   
838                   
839        mesh = Mesh(points, vertices)
840        mesh.check_integrity()
841
842        P = mesh.get_boundary_polygon(verbose=False)
843
844       
845        assert len(P) == 9
846       
847        # Note that point e appears twice!
848        assert num.allclose(P, [a, d, f, e, g, h, e, c, b])
849
850        for p in points:
851            msg = 'Point %s is not inside polygon %s'\
852            %(p, P)     
853            assert is_inside_polygon(p, P), msg             
854
855
856                                       
857           
858           
859
860    def test_boundary_polygon_IV(self):
861        """Reproduce test test_spatio_temporal_file_function_time
862        from test_util.py that looked as if it produced the wrong boundary
863        """
864
865        from mesh_factory import rectangular       
866
867        #Create a domain to hold test grid
868        #(0:15, -20:10)
869        points, vertices, boundary =\
870                rectangular(4, 4, 15, 30, origin = (0, -20))       
871
872        #####
873        mesh = Mesh(points, vertices)
874        mesh.check_integrity()
875
876        P = mesh.get_boundary_polygon()
877
878        #print P
879        assert len(P) == 16
880        for p in points:
881            assert is_inside_polygon(p, P)
882
883
884
885        #####
886        mesh = Mesh(points, vertices, boundary)
887        mesh.check_integrity()
888
889        P = mesh.get_boundary_polygon()
890
891       
892        #print P, len(P)
893        assert len(P) == 16
894
895        for p in points:
896            assert is_inside_polygon(p, P)
897
898        #print mesh.statistics()   
899
900
901
902    def test_boundary_polygon_V(self):
903        """Create a discontinuous mesh (duplicate vertices)
904        and check that boundary is as expected
905       
906        """
907
908        #Points
909        a = [0.0, 0.0] #0
910        b = [0.0, 0.5] #1
911        c = [0.0, 1.0] #2
912        d = [0.5, 0.0] #3
913        e = [0.5, 0.5] #4
914        f = [1.0, 0.0] #5
915        g = [1.0, 0.5] #6
916        h = [1.0, 1.0] #7
917        i = [1.5, 0.5] #8
918
919        #Duplicate points for triangles edg [4,3,6] (central) and
920        #gid [6,8,7] (top right boundary) to them disconnected
921        #from the others
922
923        e0 = [0.5, 0.5] #9
924        d0 = [0.5, 0.0] #10
925        g0 = [1.0, 0.5] #11
926        i0 = [1.5, 0.5] #12       
927       
928
929        points = [a, b, c, d, e, f, g, h, i, e0, d0, g0, i0]
930
931
932
933        #dea, bae, bec, fgd,
934        #edg, ghe, gfi, gih
935        #vertices = [ [3,4,0], [1,0,4], [1,4,2], [5,6,3],
936        #             [4,3,6], [6,7,4], [6,5,8], [6,8,7]]
937
938
939        #dea, bae, bec, fgd,
940        #e0d0g0, ghe, gfi, g0i0h
941        vertices = [[3,4,0], [1,0,4], [1,4,2], [5,6,3],
942                    [9,10,11], [6,7,4], [6,5,8], [11,12,7]]       
943
944        mesh = Mesh(points, vertices)
945
946        mesh.check_integrity()
947
948        P = mesh.get_boundary_polygon()
949
950        #print P
951       
952        assert len(P) == 8
953        assert num.allclose(P, [a, d, f, i, h, e, c, b])
954        assert num.allclose(P, [(0.0, 0.0), (0.5, 0.0), (1.0, 0.0), (1.5, 0.5), (1.0, 1.0), (0.5, 0.5), (0.0, 1.0), (0.0, 0.5)])
955       
956
957        for p in points:
958            #print p, P
959            assert is_inside_polygon(p, P)
960
961
962
963    def test_boundary_polygon_VI(self):
964        """test_boundary_polygon_VI(self)
965
966        Create a discontinuous mesh (duplicate vertices) from a real situation that failed
967        and check that boundary is as expected
968        """
969
970
971        from anuga.utilities.polygon import plot_polygons
972
973        # First do the continuous version of mesh
974
975        points = [[   6626.85400391,      0.        ],
976                  [      0.        ,  38246.4140625 ],
977                  [   9656.2734375 ,  68351.265625  ],
978                  [  20827.25585938,  77818.203125  ],
979                  [  32755.59375   ,  58126.9765625 ],
980                  [  35406.3359375 ,  79332.9140625 ],
981                  [  31998.23828125,  88799.84375   ],
982                  [  23288.65820313, 104704.296875  ],
983                  [  32187.57617188, 109816.4375    ],
984                  [  50364.08984375, 110763.1328125 ],
985                  [  80468.9453125 ,  96184.0546875 ],
986                  [  86149.1015625 , 129886.34375   ],
987                  [ 118715.359375  , 129886.34375   ],
988                  [ 117768.6640625 ,  85770.4296875 ],
989                  [ 101485.5390625 ,  45251.9453125 ],
990                  [  49985.4140625 ,   2272.06396484],
991                  [  51737.94140625,  90559.2109375 ],
992                  [  56659.0703125 ,  65907.6796875 ],
993                  [  75735.4765625 ,  23762.00585938],
994                  [  52341.70703125,  38563.39453125]]
995
996        triangles = [[19, 0,15],
997                     [ 2, 4, 3],
998                     [ 4, 2, 1],
999                     [ 1,19, 4],
1000                     [15,18,19],
1001                     [18,14,17],
1002                     [19, 1, 0],
1003                     [ 6, 8, 7],
1004                     [ 8, 6,16],
1005                     [10, 9,16],
1006                     [17, 5, 4],
1007                     [16,17,10],
1008                     [17,19,18],
1009                     [ 5,17,16],
1010                     [10,14,13],
1011                     [10,17,14],
1012                     [ 8,16, 9],
1013                     [12,11,10],
1014                     [10,13,12],
1015                     [19,17, 4],
1016                     [16, 6, 5]]
1017
1018        mesh = Mesh(points, triangles)
1019        mesh.check_integrity()
1020        Pref = mesh.get_boundary_polygon()
1021
1022        #plot_polygons([ensure_numeric(Pref)], 'goodP')
1023
1024        for p in points:
1025            assert is_inside_polygon(p, Pref)
1026       
1027       
1028        # Then do the discontinuous version
1029        import warnings
1030        warnings.filterwarnings('ignore')
1031
1032       
1033        points = [[  52341.70703125,  38563.39453125],
1034                  [   6626.85400391,      0.        ],
1035                  [  49985.4140625 ,   2272.06396484],
1036                  [   9656.2734375 ,  68351.265625  ],
1037                  [  32755.59375   ,  58126.9765625 ],
1038                  [  20827.25585938,  77818.203125  ],
1039                  [  32755.59375   ,  58126.9765625 ],
1040                  [   9656.2734375 ,  68351.265625  ],
1041                  [      0.        ,  38246.4140625 ],
1042                  [      0.        ,  38246.4140625 ],
1043                  [  52341.70703125,  38563.39453125],
1044                  [  32755.59375   ,  58126.9765625 ],
1045                  [  49985.4140625 ,   2272.06396484],
1046                  [  75735.4765625 ,  23762.00585938],
1047                  [  52341.70703125,  38563.39453125],
1048                  [  75735.4765625 ,  23762.00585938],
1049                  [ 101485.5390625 ,  45251.9453125 ],
1050                  [  56659.0703125 ,  65907.6796875 ],
1051                  [  52341.70703125,  38563.39453125],
1052                  [      0.        ,  38246.4140625 ],
1053                  [   6626.85400391,      0.        ],
1054                  [  31998.23828125,  88799.84375   ],
1055                  [  32187.57617188, 109816.4375    ],
1056                  [  23288.65820313, 104704.296875  ],
1057                  [  32187.57617188, 109816.4375    ],
1058                  [  31998.23828125,  88799.84375   ],
1059                  [  51737.94140625,  90559.2109375 ],
1060                  [  80468.9453125 ,  96184.0546875 ],
1061                  [  50364.08984375, 110763.1328125 ],
1062                  [  51737.94140625,  90559.2109375 ],
1063                  [  56659.0703125 ,  65907.6796875 ],
1064                  [  35406.3359375 ,  79332.9140625 ],
1065                  [  32755.59375   ,  58126.9765625 ],
1066                  [  51737.94140625,  90559.2109375 ],
1067                  [  56659.0703125 ,  65907.6796875 ],
1068                  [  80468.9453125 ,  96184.0546875 ],
1069                  [  56659.0703125 ,  65907.6796875 ],
1070                  [  52341.70703125,  38563.39453125],
1071                  [  75735.4765625 ,  23762.00585938],
1072                  [  35406.3359375 ,  79332.9140625 ],
1073                  [  56659.0703125 ,  65907.6796875 ],
1074                  [  51737.94140625,  90559.2109375 ],
1075                  [  80468.9453125 ,  96184.0546875 ],
1076                  [ 101485.5390625 ,  45251.9453125 ],
1077                  [ 117768.6640625 ,  85770.4296875 ],
1078                  [  80468.9453125 ,  96184.0546875 ],
1079                  [  56659.0703125 ,  65907.6796875 ],
1080                  [ 101485.5390625 ,  45251.9453125 ],
1081                  [  32187.57617188, 109816.4375    ],
1082                  [  51737.94140625,  90559.2109375 ],
1083                  [  50364.08984375, 110763.1328125 ],
1084                  [ 118715.359375  , 129886.34375   ],
1085                  [  86149.1015625 , 129886.34375   ],
1086                  [  80468.9453125 ,  96184.0546875 ],
1087                  [  80468.9453125 ,  96184.0546875 ],
1088                  [ 117768.6640625 ,  85770.4296875 ],
1089                  [ 118715.359375  , 129886.34375   ],
1090                  [  52341.70703125,  38563.39453125],
1091                  [  56659.0703125 ,  65907.6796875 ],
1092                  [  32755.59375   ,  58126.9765625 ],
1093                  [  51737.94140625,  90559.2109375 ],
1094                  [  31998.23828125,  88799.84375   ],
1095                  [  35406.3359375 ,  79332.9140625 ]]
1096
1097        scaled_points = ensure_numeric(points, num.int)/1000  # Simplify for ease of interpretation
1098
1099        triangles = [[ 0, 1, 2],
1100                     [ 3, 4, 5],
1101                     [ 6, 7, 8],
1102                     [ 9,10,11],
1103                     [12,13,14],
1104                     [15,16,17],
1105                     [18,19,20],
1106                     [21,22,23],
1107                     [24,25,26],
1108                     [27,28,29],
1109                     [30,31,32],
1110                     [33,34,35],
1111                     [36,37,38],
1112                     [39,40,41],
1113                     [42,43,44],
1114                     [45,46,47],
1115                     [48,49,50],
1116                     [51,52,53],
1117                     [54,55,56],
1118                     [57,58,59],
1119                     [60,61,62]]
1120
1121
1122        # First use scaled points for ease of debugging
1123        mesh = Mesh(scaled_points, triangles)
1124        mesh.check_integrity()
1125        P = mesh.get_boundary_polygon()
1126
1127        for p in scaled_points:
1128            assert is_inside_polygon(p, P)           
1129
1130        # Then use original points and test       
1131        mesh = Mesh(points, triangles)
1132        mesh.check_integrity()
1133        P = mesh.get_boundary_polygon()
1134
1135        for p in points:
1136            assert is_inside_polygon(p, P)           
1137
1138        assert num.allclose(P, Pref)   
1139
1140    def test_lone_vertices(self):
1141        a = [2.0, 1.0]
1142        b = [6.0, 2.0]
1143        c = [1.0, 3.0]
1144        d = [2.0, 4.0]
1145
1146        points = [a, b, c, d]
1147        vertices = [[0,1,2]]
1148
1149        mesh = Mesh(points, vertices)
1150        mesh.check_integrity()
1151        loners = mesh.get_lone_vertices()
1152        self.failUnless(loners==[3],
1153                        'FAILED!')
1154
1155       
1156        a = [2.0, 1.0]
1157        b = [6.0, 2.0]
1158        c = [1.0, 3.0]
1159        d = [2.0, 4.0]
1160
1161        points = [d, a, b, c]
1162        vertices = [[3,1,2]]
1163
1164        mesh = Mesh(points, vertices)
1165        mesh.check_integrity()
1166        loners = mesh.get_lone_vertices()
1167        self.failUnless(loners==[0],
1168                        'FAILED!') 
1169
1170    def test_mesh_get_boundary_polygon_with_georeferencing(self):
1171        """test_mesh_get_boundary_polygon_with_georeferencing
1172       
1173        Test that get_boundary_polygon returns absolute coordinates
1174        """
1175       
1176        # test
1177        a = [0.0, 0.0]
1178        b = [4.0, 0.0]
1179        c = [0.0, 4.0]
1180
1181        absolute_points = [a, b, c]
1182        vertices = [[0, 1, 2]]
1183       
1184        geo = Geo_reference(56, 67, -56)
1185
1186        relative_points = geo.change_points_geo_ref(absolute_points)
1187
1188        mesh = Mesh(relative_points, vertices, geo_reference=geo)
1189        boundary_polygon = mesh.get_boundary_polygon()
1190
1191        assert num.allclose(absolute_points, boundary_polygon)
1192
1193    def test_get_triangle_containing_point(self):
1194
1195        a = [0.0, 0.0]
1196        b = [0.0, 2.0]
1197        c = [2.0, 0.0]
1198        d = [0.0, 4.0]
1199        e = [2.0, 2.0]
1200        f = [4.0, 0.0]
1201
1202        points = [a, b, c, d, e, f]
1203        #bac, bce, ecf, dbe
1204        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
1205        mesh = Mesh(points, vertices)
1206       
1207        mesh.check_integrity()
1208
1209
1210        try:
1211            id = mesh.get_triangle_containing_point([3.0, 5.0])
1212        except:
1213            pass
1214        else:
1215            msg = 'Should have caught point outside polygon (Non)'           
1216            raise Exception, msg
1217           
1218        id = mesh.get_triangle_containing_point([0.5, 1.0])
1219        assert id == 0
1220
1221        id = mesh.get_triangle_containing_point([1.0, 3.0])
1222        assert id == 3       
1223
1224        for i, point in enumerate(mesh.get_centroid_coordinates()):
1225            id = mesh.get_triangle_containing_point(point)
1226            assert id == i       
1227
1228    def test_get_triangle_neighbours(self):
1229        a = [0.0, 0.0]
1230        b = [0.0, 2.0]
1231        c = [2.0,0.0]
1232        e = [2.0, 2.0]
1233        points = [a, b, c, e]
1234        vertices = [ [1,0,2], [1,2,3] ]   #bac, bce
1235        mesh = Mesh(points, vertices)
1236
1237        neighbours = mesh.get_triangle_neighbours(0)
1238        assert num.allclose(neighbours, [-1,1,-1])
1239        neighbours = mesh.get_triangle_neighbours(-10)
1240        assert neighbours == []
1241        neighbours = mesh.get_triangle_neighbours(2)
1242        assert neighbours == []
1243
1244
1245    def test_get_intersecting_segments1(self):
1246        """test_get_intersecting_segments(self):
1247
1248        Very simple test (horizontal lines)
1249        """
1250
1251        # Build test mesh
1252       
1253        # Create basic mesh
1254        # 9 points at (0,0), (0, 1), ..., (2,2)
1255        # 8 triangles enumerated from left bottom to right top.
1256        points, vertices, boundary = rectangular(2, 2, 2, 2)
1257        mesh = Mesh(points, vertices, boundary)
1258
1259        # Very simple horizontal line intersecting
1260        #
1261
1262
1263        for y_line in [0.1, 0.2, 0.314159, 0.41, 0.6, 0.99, 1.01, 1.5, 1.77, 1.9]:
1264            if y_line < 1:
1265                ceiling = 1
1266                floor = 0
1267                intersected_triangles = [0,1,4,5]
1268            elif y_line > 1:
1269                ceiling = 2
1270                floor = 1
1271                intersected_triangles = [2,3,6,7]
1272            else:
1273                raise Exception, 'this test is not for parallel lines'
1274
1275
1276            line = [[-1,y_line], [3,y_line]]
1277
1278            L = mesh.get_intersecting_segments(line)
1279            assert len(L) == 4
1280
1281           
1282
1283            # Check all normals point straight down etc
1284            total_length = 0
1285            for x in L:
1286                if x.triangle_id % 2 == 0:
1287                    assert num.allclose(x.length, ceiling-y_line)
1288                else:
1289                    assert num.allclose(x.length, y_line-floor)               
1290
1291               
1292                assert num.allclose(x.normal, [0,-1])
1293
1294                assert num.allclose(x.segment[1][0], x.segment[0][0] + x.length)
1295                assert num.allclose(x.segment[0][1], y_line)
1296                assert num.allclose(x.segment[1][1], y_line)               
1297
1298                assert x.triangle_id in intersected_triangles
1299
1300                total_length += x.length
1301
1302            msg = 'Segments do not add up'
1303            assert num.allclose(total_length, 2), msg
1304           
1305
1306    def test_get_intersecting_segments_coinciding(self):
1307        """test_get_intersecting_segments_coinciding(self):
1308
1309        Test that lines coinciding with triangle edges work.
1310        """
1311
1312        # Build test mesh
1313       
1314        # Create basic mesh
1315        # 9 points at (0,0), (0, 1), ..., (2,2)
1316        # 8 triangles enumerated from left bottom to right top.
1317        points, vertices, boundary = rectangular(2, 2, 2, 2)
1318        mesh = Mesh(points, vertices, boundary)
1319        intersected_triangles = [1,5]
1320
1321        # Very simple horizontal line intersecting
1322        #
1323
1324        y_line = 1.0
1325       
1326        line = [[-1,y_line], [3,y_line]]
1327
1328        L = mesh.get_intersecting_segments(line)
1329
1330
1331        msg = 'Only two triangles should be returned'   
1332        assert len(L) == 2, msg   
1333           
1334
1335        # Check all
1336        total_length = 0
1337        for x in L:
1338            assert num.allclose(x.length, 1.0)
1339            assert num.allclose(x.normal, [0,-1])
1340
1341            assert num.allclose(x.segment[1][0], x.segment[0][0] + x.length)
1342            assert num.allclose(x.segment[0][1], y_line)
1343            assert num.allclose(x.segment[1][1], y_line)                           
1344
1345
1346
1347            assert x.triangle_id in intersected_triangles
1348
1349            total_length += x.length
1350
1351        msg = 'Segments do not add up'
1352        assert num.allclose(total_length, 2), msg
1353       
1354
1355    def test_get_intersecting_segments_partially_coinciding(self):
1356        """test_get_intersecting_segments_partially_coinciding(self):
1357
1358        Test that line coinciding with triangle edges work.
1359        But this ones only coincide with parts of the edge.
1360        """
1361
1362        # Build test mesh
1363       
1364        # Create basic mesh
1365        # 9 points at (0,0), (0, 1), ..., (2,2)
1366        # 8 triangles enumerated from left bottom to right top.
1367        points, vertices, boundary = rectangular(2, 2, 2, 2)
1368        mesh = Mesh(points, vertices, boundary)
1369        intersected_triangles = [1,5]
1370
1371        # Horizontal line intersecting along center but stopping
1372        # parway through second triangle's edge
1373        #
1374
1375        y_line = 1.0
1376       
1377        #line = [[0, y_line], [2, y_line]]
1378        line = [[0, y_line], [1.5, y_line]]
1379
1380        L = mesh.get_intersecting_segments(line)
1381        #for x in L:
1382        #    print x
1383
1384        msg = 'Two triangles should be returned'   
1385        assert len(L) == 2, msg   
1386           
1387
1388        # Check all
1389        total_length = 0
1390        for x in L:
1391            if x.triangle_id == 1:
1392                assert num.allclose(x.length, 1)       
1393                assert num.allclose(x.normal, [0, -1])
1394               
1395            if x.triangle_id == 5:
1396                assert num.allclose(x.length, 0.5)
1397                assert num.allclose(x.normal, [0, -1])
1398
1399
1400            assert x.triangle_id in intersected_triangles
1401
1402            total_length += x.length
1403
1404        msg = 'Segments do not add up'
1405        assert num.allclose(total_length, 1.5), msg           
1406
1407
1408
1409    def test_get_intersecting_segments2(self):
1410        """test_get_intersecting_segments(self):
1411
1412        Lines with a slope
1413        """
1414
1415        s2 = sqrt(2.0)/2
1416       
1417
1418        # Build test mesh
1419       
1420        # Create basic mesh
1421        # 9 points at (0,0), (0, 1), ..., (2,2)
1422        # 8 triangles enumerated from left bottom to right top.
1423        points, vertices, boundary = rectangular(2, 2, 2, 2)
1424        mesh = Mesh(points, vertices, boundary)
1425       
1426
1427        # Diagonal cutting through a vertex and hypothenuses
1428        line = [[0, 2], [2, 0]]
1429        intersected_triangles = [3,2,5,4]               
1430
1431        L = mesh.get_intersecting_segments(line)
1432        assert len(L) == 4
1433
1434        #print L
1435       
1436        # Check all segments
1437        total_length = 0
1438        for i, x in enumerate(L): 
1439            assert num.allclose(x.length, s2)
1440            assert num.allclose(x.normal, [-s2, -s2])
1441            assert num.allclose(sum(x.normal**2), 1)
1442           
1443            assert x.triangle_id in intersected_triangles
1444
1445            total_length += x.length
1446
1447        msg = 'Segments do not add up'
1448        assert num.allclose(total_length, 4*s2), msg
1449
1450
1451        # Diagonal cutting through a vertex and hypothenuses (reversed)
1452        line = [[2, 0], [0, 2]]
1453        intersected_triangles = [3,2,5,4]               
1454
1455        L = mesh.get_intersecting_segments(line)
1456        assert len(L) == 4
1457
1458        #print L
1459       
1460        # Check all segments
1461        total_length = 0
1462        for i, x in enumerate(L): 
1463            assert num.allclose(x.length, s2)
1464            assert num.allclose(x.normal, [s2, s2])
1465            assert num.allclose(sum(x.normal**2), 1)
1466           
1467            assert x.triangle_id in intersected_triangles
1468
1469            total_length += x.length
1470
1471        msg = 'Segments do not add up'
1472        assert num.allclose(total_length, 4*s2), msg                   
1473
1474
1475
1476        # Diagonal coinciding with hypothenuses
1477        line = [[2, 2], [0, 0]]
1478        intersected_triangles = [6,0]               
1479
1480        L = mesh.get_intersecting_segments(line)
1481        assert len(L) == 2
1482
1483        #print L
1484       
1485        # Check all segments
1486        total_length = 0
1487        for i, x in enumerate(L): 
1488            assert num.allclose(x.length, 2*s2)
1489            assert num.allclose(x.normal, [-s2, s2])
1490            assert num.allclose(sum(x.normal**2), 1)
1491           
1492            assert x.triangle_id in intersected_triangles
1493
1494            total_length += x.length
1495
1496        msg = 'Segments do not add up'
1497        assert num.allclose(total_length, 4*s2), msg                       
1498
1499
1500        # Diagonal coinciding with hypothenuses (reversed)
1501        line = [[0, 0], [2, 2]]
1502        intersected_triangles = [6,0]               
1503
1504        L = mesh.get_intersecting_segments(line)
1505        assert len(L) == 2
1506
1507        #print L
1508       
1509        # Check all segments
1510        total_length = 0
1511        for i, x in enumerate(L): 
1512            assert num.allclose(x.length, 2*s2)
1513            assert num.allclose(x.normal, [s2, -s2])
1514            assert num.allclose(sum(x.normal**2), 1)
1515           
1516            assert x.triangle_id in intersected_triangles
1517
1518            total_length += x.length
1519
1520        msg = 'Segments do not add up'
1521        assert num.allclose(total_length, 4*s2), msg                       
1522
1523
1524
1525        # line with slope [1, -1] cutting through vertices of tri 7 and 6
1526        line = [[1, 2], [2, 1]]
1527        intersected_triangles = [7,6]               
1528
1529        L = mesh.get_intersecting_segments(line)
1530        assert len(L) == 2
1531
1532        #print L
1533       
1534        # Check all segments
1535        total_length = 0
1536        for i, x in enumerate(L): 
1537            assert num.allclose(x.length, s2)
1538            assert num.allclose(x.normal, [-s2, -s2])
1539            assert num.allclose(sum(x.normal**2), 1)
1540           
1541            assert x.triangle_id in intersected_triangles
1542
1543            total_length += x.length
1544
1545        msg = 'Segments do not add up'
1546        assert num.allclose(total_length, 2*s2), msg
1547
1548
1549        # Arbitrary line with slope [1, -1] cutting through tri 7 and 6
1550        line = [[1.1, 2], [2.1, 1]]
1551        intersected_triangles = [7,6]               
1552
1553        L = mesh.get_intersecting_segments(line)
1554        assert len(L) == 2
1555       
1556        # Check all segments
1557        total_length = 0
1558        for i, x in enumerate(L): 
1559            assert num.allclose(x.normal, [-s2, -s2])
1560            assert num.allclose(sum(x.normal**2), 1)
1561
1562            msg = 'Triangle %d' %x.triangle_id + ' is not in %s' %(intersected_triangles)
1563            assert x.triangle_id in intersected_triangles, msg
1564           
1565
1566
1567    def test_get_intersecting_segments3(self):
1568        """test_get_intersecting_segments(self):
1569
1570        Check that line can stop inside a triangle
1571       
1572        """
1573
1574
1575
1576        s2 = sqrt(2.0)/2
1577       
1578
1579        # Build test mesh
1580       
1581        # Create basic mesh
1582        # 9 points at (0,0), (0, 1), ..., (2,2)
1583        # 8 triangles enumerated from left bottom to right top.
1584        points, vertices, boundary = rectangular(2, 2, 2, 2)
1585        mesh = Mesh(points, vertices, boundary)
1586       
1587
1588        # Line cutting through one triangle and ending on its edge
1589        line = [[0.5, 3], [0.5, 1.5]]
1590        intersected_triangles = [3]               
1591
1592        L = mesh.get_intersecting_segments(line)
1593        assert len(L) == 1
1594        assert L[0].triangle_id == 3
1595        assert num.allclose(L[0].length, 0.5)       
1596        assert num.allclose(L[0].normal, [-1,0])               
1597
1598
1599
1600        # Now try to shorten it so that its endpoint falls short of the far edge
1601        line = [[0.5, 3], [0.5, 1.6]]
1602        intersected_triangles = [3]               
1603
1604        L = mesh.get_intersecting_segments(line)
1605        assert len(L) == 1
1606        assert L[0].triangle_id == 3
1607        assert num.allclose(L[0].length, 0.4)
1608        assert num.allclose(L[0].normal, [-1,0])
1609
1610        intersected_triangles = [3]
1611
1612        # Now the same, but with direction changed
1613        line = [[0.5, 3], [0.5, 1.6]]
1614        line = [[0.5, 1.6], [0.5, 3]]       
1615        intersected_triangles = [3]               
1616
1617        L = mesh.get_intersecting_segments(line)
1618        assert len(L) == 1
1619        assert L[0].triangle_id == 3
1620        assert num.allclose(L[0].length, 0.4)
1621        assert num.allclose(L[0].normal, [1,0])               
1622       
1623
1624           
1625
1626    def test_get_intersecting_segments4(self):
1627        """test_get_intersecting_segments(self):
1628
1629        Simple poly line
1630       
1631        """
1632
1633
1634
1635        s2 = sqrt(2.0)/2
1636       
1637
1638        # Build test mesh
1639       
1640        # Create basic mesh
1641        # 9 points at (0,0), (0, 1), ..., (2,2)
1642        # 8 triangles enumerated from left bottom to right top.
1643        points, vertices, boundary = rectangular(2, 2, 2, 2)
1644        mesh = Mesh(points, vertices, boundary)
1645       
1646
1647        # Polyline with three segments cutting through mesh
1648        line = [[0.5, 3], [0.5, 1.5], [1,1]]
1649
1650        L = mesh.get_intersecting_segments(line)
1651        assert len(L) == 2
1652
1653        for x in L:
1654            if x.triangle_id == 3:
1655                assert num.allclose(x.length, 0.5)       
1656                assert num.allclose(x.normal, [-1,0])
1657               
1658            if x.triangle_id == 2:
1659                assert num.allclose(x.length, s2)
1660                assert num.allclose(x.normal, [-s2,-s2])
1661
1662
1663
1664    def test_get_intersecting_segments5(self):
1665        """test_get_intersecting_segments(self):
1666
1667        More complex poly line
1668       
1669        """
1670
1671
1672
1673        s2 = sqrt(2.0)/2
1674       
1675
1676        # Build test mesh
1677       
1678        # Create basic mesh
1679        # 9 points at (0,0), (0, 1), ..., (2,2)
1680        # 8 triangles enumerated from left bottom to right top.
1681        points, vertices, boundary = rectangular(2, 2, 2, 2)
1682        mesh = Mesh(points, vertices, boundary)
1683       
1684
1685        # Polyline with three segments cutting through mesh
1686        line = [[0.5, 3], [0.5, 1.5], [1.25, 0.75]] 
1687
1688        L = mesh.get_intersecting_segments(line)
1689        assert len(L) == 3
1690
1691        for x in L:
1692            if x.triangle_id == 3:
1693                assert num.allclose(x.length, 0.5)       
1694                assert num.allclose(x.normal, [-1,0])
1695               
1696            if x.triangle_id == 2:
1697                msg = str(x.length)
1698                assert num.allclose(x.length, s2), msg
1699                assert num.allclose(x.normal, [-s2,-s2])
1700
1701            if x.triangle_id == 5:
1702                segvec = num.array([line[2][0]-1,
1703                                    line[2][1]-1])
1704                msg = str(x.length)
1705                assert num.allclose(x.length, sqrt(sum(segvec**2))), msg
1706                assert num.allclose(x.normal, [-s2,-s2])                                               
1707
1708
1709    def test_get_intersecting_segments6(self):
1710        """test_get_intersecting_segments(self):
1711
1712        Even more complex poly line, where line breaks within triangle 5
1713
1714        5 segments are returned even though only four triangles [3,2,5,6] are touched.
1715        Triangle 5 therefor has two segments in it.
1716       
1717        """
1718
1719
1720
1721        s2 = sqrt(2.0)/2
1722       
1723
1724        # Build test mesh
1725       
1726        # Create basic mesh
1727        # 9 points at (0,0), (0, 1), ..., (2,2)
1728        # 8 triangles enumerated from left bottom to right top.
1729        points, vertices, boundary = rectangular(2, 2, 2, 2)
1730        mesh = Mesh(points, vertices, boundary)
1731       
1732
1733        # Polyline with three segments cutting through mesh
1734        line = [[0.5, 3], [0.5, 1.5], [1.25, 0.75], [2.25, 1.75]]
1735
1736        L = mesh.get_intersecting_segments(line)
1737        #for x in L:
1738        #    print x
1739
1740        assert len(L) == 5
1741
1742        for x in L:
1743            if x.triangle_id == 3:
1744                assert num.allclose(x.length, 0.5)       
1745                assert num.allclose(x.normal, [-1,0])
1746               
1747            if x.triangle_id == 2:
1748                msg = str(x.length)
1749                assert num.allclose(x.length, s2), msg
1750                assert num.allclose(x.normal, [-s2,-s2])
1751
1752            if x.triangle_id == 5:
1753                if x.segment == ((1.0, 1.0), (1.25, 0.75)):                   
1754                    segvec = num.array([line[2][0]-1,
1755                                        line[2][1]-1])
1756                    msg = str(x.length)
1757                    assert num.allclose(x.length, sqrt(sum(segvec**2))), msg
1758                    assert num.allclose(x.normal, [-s2,-s2])
1759                elif x.segment == ((1.25, 0.75), (1.5, 1.0)):
1760                    segvec = num.array([1.5-line[2][0],
1761                                        1.0-line[2][1]])
1762                   
1763                    assert num.allclose(x.length, sqrt(sum(segvec**2))), msg
1764                    assert num.allclose(x.normal, [s2,-s2])
1765                else:
1766                    msg = 'Unknow segment: %s' %x.segment
1767                    raise Exception, msg
1768               
1769
1770                   
1771            if x.triangle_id == 6:
1772                assert num.allclose(x.normal, [s2,-s2])
1773                assert num.allclose(x.segment, ((1.5, 1.0), (2, 1.5)))
1774
1775
1776      # Internal test that sum of line segments add up
1777      # to length of input line
1778      #
1779      # Could be useful perhaps
1780      #
1781      #xi1 = line[1][0]
1782      #eta1 = line[1][1]
1783      #linevector = num.array([xi1-xi0, eta1-eta0])
1784      #linelength = sqrt(sum(linevector**2))
1785      #
1786      #segmentlength = 0
1787      #for segment in triangle_intersections:
1788      #    vector = array([segment[1][0] - segment[0][0],
1789      #                    segment[1][1] - segment[0][1]])
1790      #    length = sqrt(sum(vector**2))     
1791      #    segmentlength += length
1792      #
1793      #msg = 'Sum of intersecting segments do not add up'   
1794      #assert allclose(segmentlength, linelength), msg   
1795
1796
1797
1798
1799    def test_get_intersecting_segments7(self):
1800        """test_get_intersecting_segments(self):
1801
1802        Check that line can stop inside a triangle - this is from
1803        flow throug a cross sections example in test_datamanager.
1804       
1805        """
1806
1807        # Build test mesh
1808        width = 5
1809        length = 100
1810        t_end = 1
1811        points, vertices, boundary = rectangular(length, width,
1812                                                 length, width)
1813
1814        mesh = Mesh(points, vertices, boundary)
1815       
1816
1817        # A range of partial lines
1818        x = length/2.
1819        for i in range(10):
1820            start_point = [length/2., i*width/10.]
1821            #print
1822            #print start_point
1823                           
1824            line = [start_point, [length/2., width]]
1825 
1826            L = mesh.get_intersecting_segments(line)
1827
1828            if start_point[1] < 1:
1829                assert len(L) == 5
1830               
1831           
1832            total_length = 0   
1833            for x in L:
1834                total_length += x.length
1835               
1836
1837            ref_length = line[1][1] - line[0][1]
1838            #print ref_length, total_length
1839            assert num.allclose(total_length, ref_length)
1840
1841
1842#-------------------------------------------------------------
1843
1844if __name__ == "__main__":
1845    suite = unittest.makeSuite(Test_Mesh, 'test')
1846    runner = unittest.TextTestRunner()
1847    runner.run(suite)
Note: See TracBrowser for help on using the repository browser.