Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Meshers/GIS/Contour2geo.py
3206 views
1
#!/usr/bin/python
2
#==========================================
3
#
4
# FILE: Contour2geo.py
5
# USAGE : python Contour2geo.py -r res [-h] [-i <inputfile>] [-o <outputfile>] [--spline] ')
6
# DESCRIPTION: Create a geometry file (.geo) for Gmsh from a closed contour
7
#
8
# BUGS: ---
9
#
10
# AUTHOR: F. Gillet-Chaulet
11
# ORGANIZATION: IGE(CNRS-France)
12
#
13
# VERSION: V1
14
# CREATED: 2020-05-02
15
# MODIFIED:
16
# * 2020-05-19: prescribe mesh size using uniform background field
17
#
18
#==========================================
19
import sys, getopt
20
21
def main(argv):
22
import numpy as np
23
24
inputfile = 'Contour.txt'
25
outputfile = 'Contour.geo'
26
spline = False
27
28
found_r=False
29
try:
30
opts, args = getopt.getopt(argv,"hi:o:r:",["spline","gmsh3"])
31
except getopt.GetoptError:
32
usage()
33
sys.exit(2)
34
for opt, arg in opts:
35
if opt == '-h':
36
usage()
37
sys.exit()
38
elif opt in ("-r"):
39
el_size= arg
40
found_r=True
41
elif opt in ("-i"):
42
inputfile = arg
43
elif opt in ("-o"):
44
outputfile = arg
45
elif opt in ("--spline"):
46
spline = True
47
48
if not found_r:
49
print('missing mandatory argument -r')
50
usage()
51
sys.exit(2)
52
53
print('Input file is : %s'%(inputfile))
54
print('Output file is : %s'%(outputfile))
55
if (spline):
56
print('make contour using splines')
57
else :
58
print('make contour using compound lines')
59
60
###############
61
###############
62
if inputfile.lower().endswith('.shp'):
63
import shapefile
64
sf = shapefile.Reader(inputfile)
65
66
#number of layers
67
nlayers=len(sf)
68
print('found {0} features in the shapefile'.format(nlayers))
69
70
# index array for BC conditions
71
index=np.arange(nlayers, dtype=np.uint8)
72
73
# get shape records
74
shapeRecs = sf.shapeRecords()
75
c=0
76
for r in shapeRecs:
77
# BC given by attribute
78
if hasattr(r.record, 'BC'):
79
index[c]=r.record.BC
80
else:
81
# or shape order
82
index[c]=c+1
83
c=c+1
84
85
print('BC ordering by feature: ')
86
print(index)
87
88
# sort shapes by BC
89
sarray=np.argsort(index)
90
91
# start with first shape
92
lnum=0
93
shape = shapeRecs[sarray[lnum]]
94
95
# it works only is last point is first point of next shape
96
# check this
97
if ((lnum+1)>(nlayers-1)) :
98
nextshape=shapeRecs[sarray[0]]
99
else:
100
nextshape=shapeRecs[sarray[lnum+1]]
101
if (shape.shape.points[-1] != nextshape.shape.points[0]):
102
print('sorry only works if last point is first of next feature')
103
sys.exit(2)
104
105
# take all points except last
106
npp=len(shape.shape.points)-1
107
pts=shape.shape.points[0:npp]
108
# there will be npp lines for this BC
109
lines=[npp]
110
111
for i in range(1,len(sarray)):
112
lnum=i
113
shape = shapeRecs[sarray[lnum]]
114
# it works only is last point is first point of next shape
115
# check this
116
if ((lnum+1)>(nlayers-1)) :
117
nextshape=shapeRecs[sarray[0]]
118
else:
119
nextshape=shapeRecs[sarray[lnum+1]]
120
if (shape.shape.points[-1] != nextshape.shape.points[0]):
121
print('sorry only works if last point is first of next feature')
122
sys.exit(2)
123
124
npp=len(shape.shape.points)-1
125
pts.extend(shape.shape.points[0:npp])
126
lines.append(npp)
127
128
Contour = np.array(pts)
129
x = Contour[:,0]
130
y = Contour[:,1]
131
Npt = len(x)
132
133
else:
134
# ascii files
135
Contour = np.loadtxt(inputfile)
136
x = Contour[:,0]
137
y = Contour[:,1]
138
139
if x[0]==x[-1] and y[0]==y[-1]:
140
#print('Same first and last points in contour file')
141
Npt = len(x)-1
142
else:
143
Npt = len(x)
144
# only one closed contour
145
lines=[Npt]
146
147
print('found %i points'%Npt)
148
149
# Open the output file
150
geo = open(outputfile, 'w')
151
geo.write('// This a a geo file created using the python script Contour2geo.py // \n')
152
geo.write('Mesh.Algorithm=5; \n')
153
geo.write('// To control the element size, one can directly modify the lc value in the geo file // \n')
154
geo.write('lc = {0} ; \n'.format(el_size))
155
geo.write('// Mesh size near the boundary from prescribed value //\n')
156
geo.write('Mesh.CharacteristicLengthFromCurvature = 0; \n')
157
geo.write('Mesh.CharacteristicLengthFromPoints = 1; \n')
158
geo.write('// Give a background field with uniform value for the mesh size // \n')
159
geo.write('Mesh.CharacteristicLengthExtendFromBoundary = 0; \n')
160
geo.write('Field[1] = MathEval; \n')
161
geo.write('Field[1].F = Sprintf("%g",lc); \n')
162
geo.write('Background Field = 1; \n')
163
164
# write the points coordinates (x,y,0,lc)
165
np=0
166
for j in range(0,Npt):
167
np=np+1
168
geo.write('Point({0}) = '.format(np)+r'{'+' {0}, {1}, 0.0, lc'.format(x[j],y[j])+r'}'+'; \n')
169
170
# if spline
171
if spline:
172
173
l0=1
174
nl=1
175
for j in range(0,(len(lines)-1)):
176
geo.write('Spline({0}) = '.format(nl)+r'{')
177
lastp=lines[j]
178
for k in range(0,lastp):
179
geo.write('{0},'.format(l0+k))
180
geo.write('{0}'.format(l0+lastp) +r'}' + '; \n')
181
l0=l0+lastp
182
nl=nl+1
183
184
geo.write('Spline({0}) = '.format(nl)+r'{')
185
lastp=lines[-1]
186
for k in range(0,lastp):
187
geo.write('{0},'.format(l0+k))
188
geo.write('1}; \n')
189
190
if len(lines) == 1 :
191
geo.write('Line Loop(1) = {1}; \n')
192
else:
193
geo.write('Line Loop(1) = '+r'{'+'{0}:{1}'.format(1,len(lines)) +r'}' +'; \n')
194
195
geo.write('Plane Surface(1) = {1}; \n')
196
geo.write('Physical Surface(1) = {1}; \n')
197
198
for j in range(0,len(lines)):
199
geo.write('Physical Line({0}) = '.format(j+1) +r'{' +'{0}'.format(j+1) +r'}'+'; \n')
200
201
# else it is lines, as a spline might not work in all cases
202
else:
203
204
nl=0
205
for j in range(0,Npt-1):
206
nl=nl+1
207
geo.write('Line({0}) = '.format(nl)+r'{'+'{0},{1}'.format(j+1,j+2)+r'}'+'; \n')
208
geo.write('Line({0}) = '.format(nl+1)+r'{'+'{0},{1}'.format(j+2,1)+r'}'+'; \n')
209
210
geo.write('Curve Loop(1) = '+r'{'+'{0}:{1}'.format(1,nl+1)+r'};'+' \n')
211
geo.write('Plane Surface(1) = {1}; \n')
212
213
# create physical curves
214
l0=1
215
phy=0
216
for j in range(0,(len(lines)-1)):
217
phy=phy+1
218
lf=l0+lines[j]-1
219
geo.write('Physical Curve({0}) = '.format(phy)+r'{'+'{0}:{1}'.format(l0,lf)+r'};'+' \n')
220
l0=lf+1
221
222
phy=phy+1
223
lf=l0+lines[-1]-1
224
geo.write('Physical Curve({0}) = '.format(phy)+r'{'+'{0}:{1}'.format(l0,lf)+r'};'+' \n')
225
226
geo.write('Physical Surface(1) = {1}; \n')
227
228
geo.close()
229
230
231
def usage():
232
print('usage: Contour2geo.py -r res [-h] [-i <inputfile>] [-o <outputfile>] [--spline] ')
233
print('options:')
234
print(' -h [print help]')
235
print(' -r res [resolution]')
236
print(' -i <inputfile> [default:Contour.txt]')
237
print(' -o <outputfile> [default:Contour.geo]')
238
print(' --spline [using splines instead of compound lines]')
239
240
241
if __name__ == "__main__":
242
main(sys.argv[1:])
243
244