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

Last change on this file since 333 was 317, checked in by ole, 20 years ago

Started playing with the Cornell Room

File size: 4.7 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
66def from_polyfile(name):
67    """Read mesh from .poly file, an obj like file format
68    listing first vertex coordinates and then connectivity
69    """
70
71    from util import anglediff
72    from math import pi
73    import os.path
74    root, ext = os.path.splitext(name)
75
76    if ext == 'poly':
77        filename = name
78    else:
79        filename = name + '.poly'
80
81   
82    fid = open(filename)
83
84    points = []    #x, y
85    values = []    #z
86    vertex_values = []    #Repeated z   
87    triangles = [] #v0, v1, v2
88   
89    lines = fid.readlines()
90
91    keyword = lines[0].strip()
92    msg = 'First line in .poly file must contain the keyword: POINTS'
93    assert keyword == 'POINTS', msg
94
95    offending = 0
96    i = 1
97    while keyword == 'POINTS':
98        line = lines[i].strip()
99        i += 1
100
101        if line == 'POLYS':
102            keyword = line
103            break
104
105        fields = line.split(':')
106        assert int(fields[0]) == i-1, 'Point indices not consecutive'
107
108        #Split the three floats
109        xyz = fields[1].split()
110
111        x = float(xyz[0])
112        y = float(xyz[1])
113        z = float(xyz[2])       
114
115        points.append([x, y])
116        values.append(z)
117       
118
119    k = i   
120    while keyword == 'POLYS':
121        line = lines[i].strip()
122        i += 1
123
124        if line == 'END':
125            keyword = line
126            break
127       
128
129        fields = line.split(':')
130        assert int(fields[0]) == i-k, 'Poly indices not consecutive'
131
132        #Split the three indices
133        vvv = fields[1].split()
134
135        i0 = int(vvv[0])-1
136        i1 = int(vvv[1])-1
137        i2 = int(vvv[2])-1
138
139        #Check for and exclude degenerate areas
140        x0 = points[i0][0]
141        y0 = points[i0][1]
142        x1 = points[i1][0]
143        y1 = points[i1][1]
144        x2 = points[i2][0]
145        y2 = points[i2][1]               
146
147        area = abs((x1*y0-x0*y1)+(x2*y1-x1*y2)+(x0*y2-x2*y0))/2
148        if area > 0:
149
150            #Ensure that points are arranged in counter clock-wise order
151            v0 = [x1-x0, y1-y0]
152            v1 = [x2-x1, y2-y1]
153            v2 = [x0-x2, y0-y2]
154
155            a0 = anglediff(v1, v0)
156            a1 = anglediff(v2, v1)
157            a2 = anglediff(v0, v2)       
158
159           
160            if a0 < pi and a1 < pi and a2 < pi:
161                #all is well
162                j0 = i0
163                j1 = i1
164                j2 = i2
165            else:
166                #Swap two vertices
167                j0 = i1
168                j1 = i0
169                j2 = i2
170               
171            triangles.append([j0, j1, j2])
172            vertex_values.append([values[j0], values[j1], values[j2]])
173        else:
174            offending +=1 
175
176    print 'Removed %d offending triangles out of %d' %(offending, len(lines))
177    return points, triangles, vertex_values
Note: See TracBrowser for help on using the repository browser.