[26374] | 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
|
---|