Changeset 5287 for anuga_core/source/anuga
- Timestamp:
- May 7, 2008, 12:30:35 PM (17 years ago)
- Location:
- anuga_core/source/anuga/abstract_2d_finite_volumes
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
anuga_core/source/anuga/abstract_2d_finite_volumes/neighbour_mesh.py
r5286 r5287 901 901 902 902 903 def _get_intersecting_segments(self, line , triangle_intersections={}):903 def _get_intersecting_segments(self, line): 904 904 """Find edges intersected by line 905 905 906 906 Input: 907 line - list of two points forming a segmented line 908 triangle_intersections to be updated 907 line - list of two points forming a segmented line 909 908 Output: 910 909 list of instances of class Triangle_intersection … … 916 915 917 916 from anuga.utilities.polygon import intersection 917 from anuga.utilities.polygon import is_inside_polygon 918 918 919 919 msg = 'Line segment must contain exactly two points' 920 920 assert len(line) == 2, msg 921 921 922 # Origin of intersecting line to be used for 923 # establishing direction 924 xi0 = line[0][0] 925 eta0 = line[0][1] 926 922 927 923 928 # Check intersection with edge segments for all triangles … … 925 930 V = self.get_vertex_coordinates() 926 931 N = len(self) 927 932 triangle_intersections={} # Keep track of segments already done 928 933 for i in range(N): 929 934 # Get nodes and edge segments for each triangle … … 938 943 939 944 # Find segments that are intersected by line 940 intersections = [] 945 946 intersections = {} # Use dictionary to record points only once 941 947 for edge in edge_segments: 942 948 943 949 status, value = intersection(line, edge) 944 950 if status == 1: 945 # Normal intersection of one edge 951 # Normal intersection of one edge or vertex 952 intersections[tuple(value)] = i 946 953 947 954 # Exclude singular intersections with vertices 948 if not(allclose(value, edge[0]) or\949 allclose(value, edge[1])):950 intersections.append(value)955 #if not(allclose(value, edge[0]) or\ 956 # allclose(value, edge[1])): 957 # intersections.append(value) 951 958 952 959 if status == 2: 953 960 # Edge is sharing a segment with line 954 961 955 # Add identified line segment 956 for j in range(value.shape[0]): 957 intersections.append(value[j,:]) 962 # This is currently covered by the two 963 # vertices that would have been picked up 964 # under status == 1 965 pass 966 967 968 969 if len(intersections) == 1: 970 # Check if either line end point lies fully within this triangle 971 # If this is the case accept that as one end of the intersecting 972 # segment 973 974 poly = V[3*i:3*i+3] 975 if is_inside_polygon(line[1], poly, closed=False): 976 intersections[tuple(line[1])] = i 977 elif is_inside_polygon(line[0], poly, closed=False): 978 intersections[tuple(line[0])] = i 979 else: 980 # Ignore situations where one vertex is touch, for instance 981 continue 958 982 959 983 … … 966 990 # Calculate attributes for this segment 967 991 968 # Origin of intersecting line to be used for direction969 xi0 = line[0][0]970 eta0 = line[0][1]971 992 972 993 # End points of intersecting segment 973 x0, y0 = intersections[0] 974 x1, y1 = intersections[1] 994 points = intersections.keys() 995 x0, y0 = points[0] 996 x1, y1 = points[1] 975 997 976 998 … … 994 1016 995 1017 996 # Normal direction (right hand side relative to direction of line) 1018 # Normal direction: 1019 # Right hand side relative to line direction 997 1020 vector = array([x1 - x0, y1 - y0]) # Segment vector 998 1021 length = sqrt(sum(vector**2)) # Segment length … … 1012 1035 1013 1036 1014 #return triangle_intersections 1037 # Return segments as a list 1038 return triangle_intersections.values() 1015 1039 1016 1040 … … 1031 1055 If a polyline segment coincides with a triangle edge, 1032 1056 the the entire shared segment will be used. 1033 1034 1057 Onle one of the triangles thus intersected will be used and that 1035 1058 is the first one encoutered. 1036 1059 1037 intersections with single vertices are ignored.1060 Intersections with single vertices are ignored. 1038 1061 1039 1062 Resulting segments are unsorted … … 1044 1067 1045 1068 # For all segments in polyline 1046 triangle_intersections = {}1069 triangle_intersections = [] 1047 1070 for i, point0 in enumerate(polyline[:-1]): 1048 1071 point1 = polyline[i+1] … … 1050 1073 line = [point0, point1] 1051 1074 1052 self._get_intersecting_segments(line, triangle_intersections)1053 1054 1055 return triangle_intersections .values()1075 triangle_intersections += self._get_intersecting_segments(line) 1076 1077 1078 return triangle_intersections 1056 1079 1057 1080 -
anuga_core/source/anuga/abstract_2d_finite_volumes/test_neighbour_mesh.py
r5286 r5287 1251 1251 """test_get_intersecting_segments(self): 1252 1252 1253 Very simple test 1253 Very simple test (horizontal lines) 1254 1254 """ 1255 1255 … … 1287 1287 1288 1288 # Check all normals point straight down etc 1289 total_length = 0 1289 1290 for x in L: 1290 1291 if x.triangle_id % 2 == 0: … … 1302 1303 assert x.triangle_id in intersected_triangles 1303 1304 1305 total_length += x.length 1306 1307 msg = 'Segments do not add up' 1308 assert allclose(total_length, 2), msg 1309 1304 1310 1305 1311 def test_get_intersecting_segments_coinciding(self): … … 1333 1339 1334 1340 # Check all normals point straight down 1341 total_length = 0 1335 1342 for i, x in enumerate(L): 1336 1343 assert allclose(x.length, 1.0) … … 1345 1352 assert x.triangle_id in intersected_triangles 1346 1353 1347 1354 total_length += x.length 1355 1356 msg = 'Segments do not add up' 1357 assert allclose(total_length, 2), msg 1358 1359 1348 1360 1349 1361 def test_get_intersecting_segments2(self): 1350 1362 """test_get_intersecting_segments(self): 1351 1363 1352 More complex mesh 1353 1364 Lines with a slope 1354 1365 """ 1355 1366 1356 # Build test mesh (from bounding polygon tests 1357 1358 1359 1360 pass 1367 s2 = sqrt(2.0)/2 1368 1369 1370 # Build test mesh 1371 1372 # Create basic mesh 1373 # 9 points at (0,0), (0, 1), ..., (2,2) 1374 # 8 triangles enumerated from left bottom to right top. 1375 points, vertices, boundary = rectangular(2, 2, 2, 2) 1376 mesh = Mesh(points, vertices, boundary) 1377 1378 1379 # Diagonal cutting through a vertex and hypothenuses 1380 line = [[0, 2], [2, 0]] 1381 intersected_triangles = [3,2,5,4] 1382 1383 L = mesh.get_intersecting_segments(line) 1384 assert len(L) == 4 1385 1386 #print L 1387 1388 # Check all segments 1389 total_length = 0 1390 for i, x in enumerate(L): 1391 assert allclose(x.length, s2) 1392 assert allclose(x.normal, [-s2, -s2]) 1393 assert allclose(sum(x.normal**2), 1) 1394 1395 assert x.triangle_id in intersected_triangles 1396 1397 total_length += x.length 1398 1399 msg = 'Segments do not add up' 1400 assert allclose(total_length, 4*s2), msg 1401 1402 1403 # Diagonal cutting through a vertex and hypothenuses (reversed) 1404 line = [[2, 0], [0, 2]] 1405 intersected_triangles = [3,2,5,4] 1406 1407 L = mesh.get_intersecting_segments(line) 1408 assert len(L) == 4 1409 1410 #print L 1411 1412 # Check all segments 1413 total_length = 0 1414 for i, x in enumerate(L): 1415 assert allclose(x.length, s2) 1416 assert allclose(x.normal, [s2, s2]) 1417 assert allclose(sum(x.normal**2), 1) 1418 1419 assert x.triangle_id in intersected_triangles 1420 1421 total_length += x.length 1422 1423 msg = 'Segments do not add up' 1424 assert allclose(total_length, 4*s2), msg 1425 1426 1427 1428 # Diagonal coinciding with hypothenuses 1429 line = [[2, 2], [0, 0]] 1430 intersected_triangles = [6,0] 1431 1432 L = mesh.get_intersecting_segments(line) 1433 assert len(L) == 2 1434 1435 #print L 1436 1437 # Check all segments 1438 total_length = 0 1439 for i, x in enumerate(L): 1440 assert allclose(x.length, 2*s2) 1441 assert allclose(x.normal, [-s2, s2]) 1442 assert allclose(sum(x.normal**2), 1) 1443 1444 assert x.triangle_id in intersected_triangles 1445 1446 total_length += x.length 1447 1448 msg = 'Segments do not add up' 1449 assert allclose(total_length, 4*s2), msg 1450 1451 1452 # Diagonal coinciding with hypothenuses (reversed) 1453 line = [[0, 0], [2, 2]] 1454 intersected_triangles = [6,0] 1455 1456 L = mesh.get_intersecting_segments(line) 1457 assert len(L) == 2 1458 1459 #print L 1460 1461 # Check all segments 1462 total_length = 0 1463 for i, x in enumerate(L): 1464 assert allclose(x.length, 2*s2) 1465 assert allclose(x.normal, [s2, -s2]) 1466 assert allclose(sum(x.normal**2), 1) 1467 1468 assert x.triangle_id in intersected_triangles 1469 1470 total_length += x.length 1471 1472 msg = 'Segments do not add up' 1473 assert allclose(total_length, 4*s2), msg 1474 1475 1476 1477 # line with slope [1, -1] cutting through vertices of tri 7 and 6 1478 line = [[1, 2], [2, 1]] 1479 intersected_triangles = [7,6] 1480 1481 L = mesh.get_intersecting_segments(line) 1482 assert len(L) == 2 1483 1484 #print L 1485 1486 # Check all segments 1487 total_length = 0 1488 for i, x in enumerate(L): 1489 assert allclose(x.length, s2) 1490 assert allclose(x.normal, [-s2, -s2]) 1491 assert allclose(sum(x.normal**2), 1) 1492 1493 assert x.triangle_id in intersected_triangles 1494 1495 total_length += x.length 1496 1497 msg = 'Segments do not add up' 1498 assert allclose(total_length, 2*s2), msg 1499 1500 1501 # Arbitrary line with slope [1, -1] cutting through tri 7 and 6 1502 line = [[1.1, 2], [2.1, 1]] 1503 intersected_triangles = [7,6] 1504 1505 L = mesh.get_intersecting_segments(line) 1506 assert len(L) == 2 1507 1508 # Check all segments 1509 total_length = 0 1510 for i, x in enumerate(L): 1511 assert allclose(x.normal, [-s2, -s2]) 1512 assert allclose(sum(x.normal**2), 1) 1513 1514 msg = 'Triangle %d' %x.triangle_id + ' is not in %s' %(intersected_triangles) 1515 assert x.triangle_id in intersected_triangles, msg 1516 1517 1518 1519 def test_get_intersecting_segments3(self): 1520 """test_get_intersecting_segments(self): 1521 1522 Check that line can stop inside a triangle 1523 1524 """ 1525 1526 1527 1528 s2 = sqrt(2.0)/2 1529 1530 1531 # Build test mesh 1532 1533 # Create basic mesh 1534 # 9 points at (0,0), (0, 1), ..., (2,2) 1535 # 8 triangles enumerated from left bottom to right top. 1536 points, vertices, boundary = rectangular(2, 2, 2, 2) 1537 mesh = Mesh(points, vertices, boundary) 1538 1539 1540 # Line cutting through one triangle and ending on its edge 1541 line = [[0.5, 3], [0.5, 1.5]] 1542 intersected_triangles = [3] 1543 1544 L = mesh.get_intersecting_segments(line) 1545 assert len(L) == 1 1546 assert L[0].triangle_id == 3 1547 assert allclose(L[0].length, 0.5) 1548 assert allclose(L[0].normal, [-1,0]) 1549 1550 1551 1552 # Now try to shorten it so that its endpoint falls short of the far edge 1553 line = [[0.5, 3], [0.5, 1.6]] 1554 intersected_triangles = [3] 1555 1556 L = mesh.get_intersecting_segments(line) 1557 assert len(L) == 1 1558 assert L[0].triangle_id == 3 1559 assert allclose(L[0].length, 0.4) 1560 assert allclose(L[0].normal, [-1,0]) 1561 1562 intersected_triangles = [3] 1563 1564 # Now the same, but with direction changed 1565 line = [[0.5, 3], [0.5, 1.6]] 1566 line = [[0.5, 1.6], [0.5, 3]] 1567 intersected_triangles = [3] 1568 1569 L = mesh.get_intersecting_segments(line) 1570 assert len(L) == 1 1571 assert L[0].triangle_id == 3 1572 assert allclose(L[0].length, 0.4) 1573 assert allclose(L[0].normal, [1,0]) 1574 1575 1576 1577 1578 def test_get_intersecting_segments4(self): 1579 """test_get_intersecting_segments(self): 1580 1581 Simple poly line 1582 1583 """ 1584 1585 1586 1587 s2 = sqrt(2.0)/2 1588 1589 1590 # Build test mesh 1591 1592 # Create basic mesh 1593 # 9 points at (0,0), (0, 1), ..., (2,2) 1594 # 8 triangles enumerated from left bottom to right top. 1595 points, vertices, boundary = rectangular(2, 2, 2, 2) 1596 mesh = Mesh(points, vertices, boundary) 1597 1598 1599 # Polyline with three segments cutting through mesh 1600 line = [[0.5, 3], [0.5, 1.5], [1,1]] 1601 1602 L = mesh.get_intersecting_segments(line) 1603 assert len(L) == 2 1604 1605 for x in L: 1606 if x.triangle_id == 3: 1607 assert allclose(x.length, 0.5) 1608 assert allclose(x.normal, [-1,0]) 1609 1610 if x.triangle_id == 2: 1611 assert allclose(x.length, s2) 1612 assert allclose(x.normal, [-s2,-s2]) 1613 1614 1615 1616 def test_get_intersecting_segments5(self): 1617 """test_get_intersecting_segments(self): 1618 1619 More complex poly line 1620 1621 """ 1622 1623 1624 1625 s2 = sqrt(2.0)/2 1626 1627 1628 # Build test mesh 1629 1630 # Create basic mesh 1631 # 9 points at (0,0), (0, 1), ..., (2,2) 1632 # 8 triangles enumerated from left bottom to right top. 1633 points, vertices, boundary = rectangular(2, 2, 2, 2) 1634 mesh = Mesh(points, vertices, boundary) 1635 1636 1637 # Polyline with three segments cutting through mesh 1638 line = [[0.5, 3], [0.5, 1.5], [1.25, 0.75]] 1639 1640 L = mesh.get_intersecting_segments(line) 1641 assert len(L) == 3 1642 1643 for x in L: 1644 if x.triangle_id == 3: 1645 assert allclose(x.length, 0.5) 1646 assert allclose(x.normal, [-1,0]) 1647 1648 if x.triangle_id == 2: 1649 msg = str(x.length) 1650 assert allclose(x.length, s2), msg 1651 assert allclose(x.normal, [-s2,-s2]) 1652 1653 if x.triangle_id == 5: 1654 segvec = array([line[2][0]-1, 1655 line[2][1]-1]) 1656 msg = str(x.length) 1657 assert allclose(x.length, sqrt(sum(segvec**2))), msg 1658 assert allclose(x.normal, [-s2,-s2]) 1659 1660 1661 def test_get_intersecting_segments6(self): 1662 """test_get_intersecting_segments(self): 1663 1664 Even more complex poly line, where line breaks within triangle 5 1665 1666 5 segments are returned even though only four triangles [3,2,5,6] are touched. 1667 Triangle 5 therefor has two segments in it. 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], [2.25, 1.75]] 1687 1688 L = mesh.get_intersecting_segments(line) 1689 #for x in L: 1690 # print x 1691 1692 assert len(L) == 5 1693 1694 for x in L: 1695 if x.triangle_id == 3: 1696 assert allclose(x.length, 0.5) 1697 assert allclose(x.normal, [-1,0]) 1698 1699 if x.triangle_id == 2: 1700 msg = str(x.length) 1701 assert allclose(x.length, s2), msg 1702 assert allclose(x.normal, [-s2,-s2]) 1703 1704 if x.triangle_id == 5: 1705 if x.segment == ((1.0, 1.0), (1.25, 0.75)): 1706 segvec = array([line[2][0]-1, 1707 line[2][1]-1]) 1708 msg = str(x.length) 1709 assert allclose(x.length, sqrt(sum(segvec**2))), msg 1710 assert allclose(x.normal, [-s2,-s2]) 1711 elif x.segment == ((1.25, 0.75), (1.5, 1.0)): 1712 segvec = array([1.5-line[2][0], 1713 1.0-line[2][1]]) 1714 1715 assert allclose(x.length, sqrt(sum(segvec**2))), msg 1716 assert allclose(x.normal, [s2,-s2]) 1717 else: 1718 msg = 'Unknow segment: %s' %x.segment 1719 raise Exception, msg 1720 1721 1722 1723 if x.triangle_id == 6: 1724 assert allclose(x.normal, [s2,-s2]) 1725 assert allclose(x.segment, ((1.5, 1.0), (2, 1.5))) 1726 1727 1728 # Internal test that sum of line segments add up 1729 # to length of input line 1730 # 1731 # Could be useful perhaps 1732 # 1733 #xi1 = line[1][0] 1734 #eta1 = line[1][1] 1735 #linevector = array([xi1-xi0, eta1-eta0]) 1736 #linelength = sqrt(sum(linevector**2)) 1737 # 1738 #segmentlength = 0 1739 #for segment in triangle_intersections: 1740 # vector = array([segment[1][0] - segment[0][0], 1741 # segment[1][1] - segment[0][1]]) 1742 # length = sqrt(sum(vector**2)) 1743 # segmentlength += length 1744 # 1745 #msg = 'Sum of intersecting segments do not add up' 1746 #assert allclose(segmentlength, linelength), msg 1747 1748 1361 1749 1362 1750 #------------------------------------------------------------- … … 1364 1752 #suite = unittest.makeSuite(Test_Mesh,'test_two_triangles') 1365 1753 #suite = unittest.makeSuite(Test_Mesh,'test_get_intersecting_segments_coinciding') 1366 suite = unittest.makeSuite(Test_Mesh,'test') 1754 suite = unittest.makeSuite(Test_Mesh,'test') #_get_intersecting_segments6') 1367 1755 runner = unittest.TextTestRunner() 1368 1756 runner.run(suite)
Note: See TracChangeset
for help on using the changeset viewer.