1 | import os.path
|
---|
2 | import numpy as np
|
---|
3 | from collections import OrderedDict
|
---|
4 |
|
---|
5 | def contourlevelzero(md,mask,level):
|
---|
6 | """CONTOURLEVELZERO - figure out the zero level (or offset thereof, specified by the level value)
|
---|
7 | of a vectorial mask, and vectorialize it into an exp or shp compatible structure.
|
---|
8 |
|
---|
9 | Usage:
|
---|
10 | contours=contourlevelzero(md,mask,level)
|
---|
11 |
|
---|
12 | See also: PLOT_CONTOUR
|
---|
13 | """
|
---|
14 |
|
---|
15 | #process data
|
---|
16 | if md.mesh.dimension()==3:
|
---|
17 | x = md.mesh.x2d
|
---|
18 | y = md.mesh.y2d
|
---|
19 | z=md.mesh.z
|
---|
20 | index=md.mesh.elements2d-1
|
---|
21 | else:
|
---|
22 | x=md.mesh.x
|
---|
23 | y=md.mesh.y
|
---|
24 | index=md.mesh.elements-1
|
---|
25 | z=np.zeros((md.mesh.numberofvertices,1))
|
---|
26 |
|
---|
27 | if len(mask)==0:
|
---|
28 | raise OSError("mask provided is empty")
|
---|
29 |
|
---|
30 | if md.mesh.dimension()==3:
|
---|
31 | if len(mask)!=md.mesh.numberofvertices2d:
|
---|
32 | raise OSError("mask provided should be specified at the vertices of the mesh")
|
---|
33 | else:
|
---|
34 | if len(mask)!=md.mesh.numberofvertices:
|
---|
35 | raise OSError("mask provided should be specified at the vertices of the mesh")
|
---|
36 |
|
---|
37 | #initialization of some variables
|
---|
38 | numberofelements=np.size(index,0)
|
---|
39 | elementslist=np.c_[0:numberofelements]
|
---|
40 | c=[]
|
---|
41 | h=[]
|
---|
42 |
|
---|
43 | #get unique edges in mesh
|
---|
44 | #1: list of edges
|
---|
45 | edges=np.vstack((np.vstack((index[:,(0,1)],index[:,(1,2)])),index[:,(2,0)]))
|
---|
46 |
|
---|
47 | #2: find unique edges
|
---|
48 | [edges,J]=np.unique(np.sort(edges,1),axis=0,return_inverse=True)
|
---|
49 | #3: unique edge numbers
|
---|
50 | vec=J
|
---|
51 | #4: unique edges numbers in each triangle (2 triangles sharing the same edge will have
|
---|
52 | # the same edge number)
|
---|
53 | edges_tria=np.hstack((np.hstack((vec[elementslist],vec[elementslist+numberofelements])),vec[elementslist+2*numberofelements]))
|
---|
54 |
|
---|
55 | #segments [nodes1 nodes2]
|
---|
56 | Seg1=index[:,(0,1)]
|
---|
57 | Seg2=index[:,(1,2)]
|
---|
58 | Seg3=index[:,(2,0)]
|
---|
59 |
|
---|
60 | #segment numbers [1;4;6;...]
|
---|
61 | Seg1_num=edges_tria[:,0]
|
---|
62 | Seg2_num=edges_tria[:,1]
|
---|
63 | Seg3_num=edges_tria[:,2]
|
---|
64 |
|
---|
65 | #value of data on each tips of the segments
|
---|
66 | Data1=mask[Seg1]
|
---|
67 | Data2=mask[Seg2]
|
---|
68 | Data3=mask[Seg3]
|
---|
69 |
|
---|
70 | #get the ranges for each segment
|
---|
71 | Range1=np.sort(Data1,1)
|
---|
72 | Range2=np.sort(Data2,1)
|
---|
73 | Range3=np.sort(Data3,1)
|
---|
74 |
|
---|
75 | #find the segments that contain this value
|
---|
76 | pos1=(Range1[:,0]<level) & (Range1[:,1]>=level)
|
---|
77 | pos2=(Range2[:,0]<level) & (Range2[:,1]>=level)
|
---|
78 | pos3=(Range3[:,0]<level) & (Range3[:,1]>=level)
|
---|
79 |
|
---|
80 | #get elements
|
---|
81 | poselem12=(pos1) & (pos2)
|
---|
82 | poselem13=(pos1) & (pos3)
|
---|
83 | poselem23=(pos2) & (pos3)
|
---|
84 | poselem=np.where((poselem12) | (poselem13) | (poselem23))
|
---|
85 | poselem=poselem[0]
|
---|
86 | numelems=len(poselem)
|
---|
87 |
|
---|
88 | #if no element has been flagged, skip to the next level
|
---|
89 | if numelems==0:
|
---|
90 | raise Exception('contourlevelzero warning message: no elements found with corresponding level value in mask')
|
---|
91 | contours=[]
|
---|
92 | return contours
|
---|
93 |
|
---|
94 | #go through the elements and build the coordinates for each segment (1 by element)
|
---|
95 | x1=np.zeros((numelems,1))
|
---|
96 | x2=np.zeros((numelems,1))
|
---|
97 | y1=np.zeros((numelems,1))
|
---|
98 | y2=np.zeros((numelems,1))
|
---|
99 | z1=np.zeros((numelems,1))
|
---|
100 | z2=np.zeros((numelems,1))
|
---|
101 |
|
---|
102 | edge_l=np.zeros((numelems,2))
|
---|
103 |
|
---|
104 | for j in range(0,numelems):
|
---|
105 |
|
---|
106 | with np.errstate(divide='ignore', invalid='ignore'):
|
---|
107 | weight1=np.divide(level-Data1[poselem[j],0],Data1[poselem[j],1]-Data1[poselem[j],0])
|
---|
108 | weight2=np.divide(level-Data2[poselem[j],0],Data2[poselem[j],1]-Data2[poselem[j],0])
|
---|
109 | weight3=np.divide(level-Data3[poselem[j],0],Data3[poselem[j],1]-Data3[poselem[j],0])
|
---|
110 |
|
---|
111 | if poselem12[poselem[j]]==True:
|
---|
112 |
|
---|
113 | x1[j]=x[Seg1[poselem[j],0]]+weight1*[x[Seg1[poselem[j],1]]-x[Seg1[poselem[j],0]]]
|
---|
114 | x2[j]=x[Seg2[poselem[j],0]]+weight2*[x[Seg2[poselem[j],1]]-x[Seg2[poselem[j],0]]]
|
---|
115 | y1[j]=y[Seg1[poselem[j],0]]+weight1*[y[Seg1[poselem[j],1]]-y[Seg1[poselem[j],0]]]
|
---|
116 | y2[j]=y[Seg2[poselem[j],0]]+weight2*[y[Seg2[poselem[j],1]]-y[Seg2[poselem[j],0]]]
|
---|
117 | z1[j]=z[Seg1[poselem[j],0]]+weight1*[z[Seg1[poselem[j],1]]-z[Seg1[poselem[j],0]]]
|
---|
118 | z2[j]=z[Seg2[poselem[j],0]]+weight2*[z[Seg2[poselem[j],1]]-z[Seg2[poselem[j],0]]]
|
---|
119 |
|
---|
120 | edge_l[j,0]=Seg1_num[poselem[j]]
|
---|
121 | edge_l[j,1]=Seg2_num[poselem[j]]
|
---|
122 | elif poselem13[poselem[j]]==True:
|
---|
123 |
|
---|
124 | x1[j]=x[Seg1[poselem[j],0]]+weight1*[x[Seg1[poselem[j],1]]-x[Seg1[poselem[j],0]]]
|
---|
125 | x2[j]=x[Seg3[poselem[j],0]]+weight3*[x[Seg3[poselem[j],1]]-x[Seg3[poselem[j],0]]]
|
---|
126 | y1[j]=y[Seg1[poselem[j],0]]+weight1*[y[Seg1[poselem[j],1]]-y[Seg1[poselem[j],0]]]
|
---|
127 | y2[j]=y[Seg3[poselem[j],0]]+weight3*[y[Seg3[poselem[j],1]]-y[Seg3[poselem[j],0]]]
|
---|
128 | z1[j]=z[Seg1[poselem[j],0]]+weight1*[z[Seg1[poselem[j],1]]-z[Seg1[poselem[j],0]]]
|
---|
129 | z2[j]=z[Seg3[poselem[j],0]]+weight3*[z[Seg3[poselem[j],1]]-z[Seg3[poselem[j],0]]]
|
---|
130 |
|
---|
131 | edge_l[j,0]=Seg1_num[poselem[j]]
|
---|
132 | edge_l[j,1]=Seg3_num[poselem[j]]
|
---|
133 | elif poselem23[poselem[j]]==True:
|
---|
134 |
|
---|
135 | x1[j]=x[Seg2[poselem[j],0]]+weight2*[x[Seg2[poselem[j],1]]-x[Seg2[poselem[j],0]]]
|
---|
136 | x2[j]=x[Seg3[poselem[j],0]]+weight3*[x[Seg3[poselem[j],1]]-x[Seg3[poselem[j],0]]]
|
---|
137 | y1[j]=y[Seg2[poselem[j],0]]+weight2*[y[Seg2[poselem[j],1]]-y[Seg2[poselem[j],0]]]
|
---|
138 | y2[j]=y[Seg3[poselem[j],0]]+weight3*[y[Seg3[poselem[j],1]]-y[Seg3[poselem[j],0]]]
|
---|
139 | z1[j]=z[Seg2[poselem[j],0]]+weight2*[z[Seg2[poselem[j],1]]-z[Seg2[poselem[j],0]]]
|
---|
140 | z2[j]=z[Seg3[poselem[j],0]]+weight3*[z[Seg3[poselem[j],1]]-z[Seg3[poselem[j],0]]]
|
---|
141 |
|
---|
142 | edge_l[j,0]=Seg2_num[poselem[j]]
|
---|
143 | edge_l[j,1]=Seg3_num[poselem[j]]
|
---|
144 |
|
---|
145 | #else:
|
---|
146 | #it shoud not go here
|
---|
147 |
|
---|
148 | #now that we have the segments, we must try to connect them...
|
---|
149 |
|
---|
150 | #loop over the subcontours
|
---|
151 | contours=[]
|
---|
152 |
|
---|
153 | while len(edge_l)>0:
|
---|
154 |
|
---|
155 | #take the right edge of the second segment and connect it to the next segments if any
|
---|
156 | e1=edge_l[0,0]
|
---|
157 | e2=edge_l[0,1]
|
---|
158 | xc=np.vstack((x1[0],x2[0]))
|
---|
159 | yc=np.vstack((y1[0],y2[0]))
|
---|
160 | zc=np.vstack((z1[0],z2[0]))
|
---|
161 | #erase the lines corresponding to this edge
|
---|
162 | edge_l=np.delete(edge_l,0,axis=0)
|
---|
163 | x1=np.delete(x1,0,axis=0)
|
---|
164 | x2=np.delete(x2,0,axis=0)
|
---|
165 | y1=np.delete(y1,0,axis=0)
|
---|
166 | y2=np.delete(y2,0,axis=0)
|
---|
167 | z1=np.delete(z1,0,axis=0)
|
---|
168 | z2=np.delete(z2,0,axis=0)
|
---|
169 | pos1=np.where(edge_l==e1)
|
---|
170 |
|
---|
171 | while len(pos1[0])>0:
|
---|
172 |
|
---|
173 | if np.all(pos1[1]==0):
|
---|
174 | xc=np.vstack((x2[pos1[0]],xc))
|
---|
175 | yc=np.vstack((y2[pos1[0]],yc))
|
---|
176 | zc=np.vstack((z2[pos1[0]],zc))
|
---|
177 | #next edge:
|
---|
178 | e1=edge_l[pos1[0],1]
|
---|
179 | else:
|
---|
180 | xc=np.vstack((x1[pos1[0]],xc))
|
---|
181 | yc=np.vstack((y1[pos1[0]],yc))
|
---|
182 | zc=np.vstack((z1[pos1[0]],zc))
|
---|
183 | #next edge:
|
---|
184 | e1=edge_l[pos1[0],0]
|
---|
185 |
|
---|
186 | #erase the lines of this
|
---|
187 | edge_l=np.delete(edge_l,pos1[0],axis=0)
|
---|
188 | x1=np.delete(x1,pos1[0],axis=0)
|
---|
189 | x2=np.delete(x2,pos1[0],axis=0)
|
---|
190 | y1=np.delete(y1,pos1[0],axis=0)
|
---|
191 | y2=np.delete(y2,pos1[0],axis=0)
|
---|
192 | z1=np.delete(z1,pos1[0],axis=0)
|
---|
193 | z2=np.delete(z2,pos1[0],axis=0)
|
---|
194 | #next connection
|
---|
195 | pos1=np.where(edge_l==e1)
|
---|
196 |
|
---|
197 | #same thing the other way (to the right)
|
---|
198 | pos2=np.where(edge_l==e2)
|
---|
199 |
|
---|
200 | while len(pos2[0])>0:
|
---|
201 |
|
---|
202 | if np.all(pos2[1]==0):
|
---|
203 | xc=np.vstack((xc,x2[pos2[0]]))
|
---|
204 | yc=np.vstack((yc,y2[pos2[0]]))
|
---|
205 | zc=np.vstack((zc,z2[pos2[0]]))
|
---|
206 | #next edge:
|
---|
207 | e2=edge_l[pos2[0],1]
|
---|
208 | else:
|
---|
209 | xc=np.vstack((xc,x1[pos2[0]]))
|
---|
210 | yc=np.vstack((yc,y1[pos2[0]]))
|
---|
211 | zc=np.vstack((zc,z1[pos2[0]]))
|
---|
212 | #next edge:
|
---|
213 | e2=edge_l[pos2[0],0]
|
---|
214 |
|
---|
215 | #erase the lines of this
|
---|
216 | edge_l=np.delete(edge_l,pos2[0],axis=0)
|
---|
217 | x1=np.delete(x1,pos2[0],axis=0)
|
---|
218 | x2=np.delete(x2,pos2[0],axis=0)
|
---|
219 | y1=np.delete(y1,pos2[0],axis=0)
|
---|
220 | y2=np.delete(y2,pos2[0],axis=0)
|
---|
221 | z1=np.delete(z1,pos2[0],axis=0)
|
---|
222 | z2=np.delete(z2,pos2[0],axis=0)
|
---|
223 | #next connection
|
---|
224 | pos2=np.where(edge_l==e2)
|
---|
225 |
|
---|
226 | #save xc,yc contour:
|
---|
227 | newcontour = OrderedDict()
|
---|
228 | newcontour['nods'] = np.size(xc)
|
---|
229 | newcontour['density'] = 1
|
---|
230 | newcontour['closed'] = 0
|
---|
231 | newcontour['x'] = np.ma.filled(xc.astype(float), np.nan)
|
---|
232 | newcontour['y'] = np.ma.filled(yc.astype(float), np.nan)
|
---|
233 | newcontour['z'] = np.ma.filled(zc.astype(float), np.nan)
|
---|
234 | newcontour['name'] = ''
|
---|
235 | contours.append(newcontour)
|
---|
236 |
|
---|
237 | return contours
|
---|