source: inundation/ga/storm_surge/pyvolution/mesh_factory.py @ 525

Last change on this file since 525 was 488, checked in by ole, 20 years ago

Played with regridding of Cornell data

File size: 4.6 KB
Line 
1"""Library of standard meshes and facilities for reading various
2mesh file formats
3"""
4
5
6def rectangular(m, n, len1=1.0, len2=1.0, origin = (0.0, 0.0)):
7
8    """Setup a rectangular grid of triangles
9    with m+1 by n+1 grid points
10    and side lengths len1, len2. If side lengths are omitted
11    the mesh defaults to the unit square.
12   
13    len1: x direction (left to right)
14    len2: y direction (bottom to top)
15
16    Return to lists: points and elements suitable for creating a Mesh or
17    FVMesh object, e.g. Mesh(points, elements)
18    """
19
20    from config import epsilon
21   
22    #E = m*n*2        #Number of triangular elements
23    #P = (m+1)*(n+1)  #Number of initial vertices
24
25    delta1 = float(len1)/m
26    delta2 = float(len2)/n   
27
28    #Dictionary of vertex objects
29    vertices = {}
30    points = []
31
32    for i in range(m+1):
33        for j in range(n+1):
34            vertices[i,j] = len(points)
35            points.append([i*delta1 + origin[0], j*delta2 + origin[1]])
36
37
38
39    #Construct 2 triangles per rectangular element and assign tags to boundary
40    elements = []
41    boundary = {}
42    for i in range(m):
43        for j in range(n):
44            v1 = vertices[i,j+1]
45            v2 = vertices[i,j]           
46            v3 = vertices[i+1,j+1]           
47            v4 = vertices[i+1,j]           
48
49            #Update boundary dictionary and create elements
50            if i == m-1:
51                boundary[(len(elements), 2)] = 'right'
52            if j == 0:
53                boundary[(len(elements), 1)] = 'bottom'               
54            elements.append([v4,v3,v2]) #Lower element
55
56            if i == 0:
57                boundary[(len(elements), 2)] = 'left'
58            if j == n-1:
59                boundary[(len(elements), 1)] = 'top' 
60            elements.append([v1,v2,v3]) #Upper element   
61
62    return points, elements, boundary       
63
64
65#FIXME: Get oblique and contracting and circular meshes from Chris
66
67
68def from_polyfile(name):
69    """Read mesh from .poly file, an obj like file format
70    listing first vertex coordinates and then connectivity
71    """
72
73    from util import anglediff
74    from math import pi
75    import os.path
76    root, ext = os.path.splitext(name)
77
78    if ext == 'poly':
79        filename = name
80    else:
81        filename = name + '.poly'
82
83   
84    fid = open(filename)
85
86    points = []    #x, y
87    values = []    #z
88    ##vertex_values = []    #Repeated z   
89    triangles = [] #v0, v1, v2
90   
91    lines = fid.readlines()
92
93    keyword = lines[0].strip()
94    msg = 'First line in .poly file must contain the keyword: POINTS'
95    assert keyword == 'POINTS', msg
96
97    offending = 0
98    i = 1
99    while keyword == 'POINTS':
100        line = lines[i].strip()
101        i += 1
102
103        if line == 'POLYS':
104            keyword = line
105            break
106
107        fields = line.split(':')
108        assert int(fields[0]) == i-1, 'Point indices not consecutive'
109
110        #Split the three floats
111        xyz = fields[1].split()
112
113        x = float(xyz[0])
114        y = float(xyz[1])
115        z = float(xyz[2])       
116
117        points.append([x, y])
118        values.append(z)
119       
120
121    k = i   
122    while keyword == 'POLYS':
123        line = lines[i].strip()
124        i += 1
125
126        if line == 'END':
127            keyword = line
128            break
129       
130
131        fields = line.split(':')
132        assert int(fields[0]) == i-k, 'Poly indices not consecutive'
133
134        #Split the three indices
135        vvv = fields[1].split()
136
137        i0 = int(vvv[0])-1
138        i1 = int(vvv[1])-1
139        i2 = int(vvv[2])-1
140
141        #Check for and exclude degenerate areas
142        x0 = points[i0][0]
143        y0 = points[i0][1]
144        x1 = points[i1][0]
145        y1 = points[i1][1]
146        x2 = points[i2][0]
147        y2 = points[i2][1]               
148
149        area = abs((x1*y0-x0*y1)+(x2*y1-x1*y2)+(x0*y2-x2*y0))/2
150        if area > 0:
151
152            #Ensure that points are arranged in counter clock-wise order
153            v0 = [x1-x0, y1-y0]
154            v1 = [x2-x1, y2-y1]
155            v2 = [x0-x2, y0-y2]
156
157            a0 = anglediff(v1, v0)
158            a1 = anglediff(v2, v1)
159            a2 = anglediff(v0, v2)       
160
161           
162            if a0 < pi and a1 < pi and a2 < pi:
163                #all is well
164                j0 = i0
165                j1 = i1
166                j2 = i2
167            else:
168                #Swap two vertices
169                j0 = i1
170                j1 = i0
171                j2 = i2
172               
173            triangles.append([j0, j1, j2])
174            ##vertex_values.append([values[j0], values[j1], values[j2]])
175        else:
176            offending +=1 
177
178    print 'Removed %d offending triangles out of %d' %(offending, len(lines))
179    return points, triangles, values
Note: See TracBrowser for help on using the repository browser.