femagtools 1.6.4__py3-none-any.whl → 1.6.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- femagtools/__init__.py +1 -1
- femagtools/dxfsl/area.py +28 -2
- femagtools/dxfsl/areabuilder.py +152 -5
- femagtools/dxfsl/concat.py +7 -7
- femagtools/dxfsl/converter.py +20 -7
- femagtools/dxfsl/dxfparser.py +359 -0
- femagtools/dxfsl/femparser.py +78 -0
- femagtools/dxfsl/geom.py +14 -426
- femagtools/dxfsl/journal.py +15 -23
- femagtools/dxfsl/machine.py +13 -3
- femagtools/dxfsl/shape.py +13 -3
- femagtools/dxfsl/svgparser.py +90 -0
- femagtools/dxfsl/symmetry.py +370 -0
- femagtools/isa7.py +6 -5
- femagtools/machine/effloss.py +1 -1
- femagtools/machine/im.py +3 -2
- femagtools/machine/pm.py +71 -12
- femagtools/machine/sm.py +4 -2
- femagtools/machine/utils.py +5 -5
- femagtools/plot/nc.py +3 -3
- femagtools/svgfsl/converter.py +74 -0
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/METADATA +5 -1
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/RECORD +28 -22
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/entry_points.txt +1 -0
- tests/test_dxfsl.py +12 -0
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/LICENSE +0 -0
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/WHEEL +0 -0
- {femagtools-1.6.4.dist-info → femagtools-1.6.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,359 @@
|
|
1
|
+
import logging
|
2
|
+
import numpy as np
|
3
|
+
from .shape import Circle, Arc, Line, Element
|
4
|
+
from .functions import distance
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
def polylines(entity, lf, rf, xoff=0.0, yoff=0.0, rotation=0.0):
|
9
|
+
"""returns a collection of bulged vertices
|
10
|
+
http://www.afralisp.net/archive/lisp/Bulges1.htm
|
11
|
+
"""
|
12
|
+
if isinstance(entity.points, list):
|
13
|
+
points = [(p[0], p[1]) for p in entity.points]
|
14
|
+
else:
|
15
|
+
points = [(p[0], p[1]) for p in entity.points()]
|
16
|
+
i = 0
|
17
|
+
if isinstance(entity.vertices, list):
|
18
|
+
vertices = entity.vertices
|
19
|
+
else:
|
20
|
+
vertices = entity.vertices()
|
21
|
+
|
22
|
+
for v in vertices:
|
23
|
+
if hasattr(v, 'bulge'):
|
24
|
+
b = v.bulge
|
25
|
+
else:
|
26
|
+
b = v.get_dxf_attrib('bulge', 0.0)
|
27
|
+
p1 = points[i]
|
28
|
+
try:
|
29
|
+
p2 = points[i+1]
|
30
|
+
except Exception:
|
31
|
+
if not entity.is_closed:
|
32
|
+
break
|
33
|
+
p2 = points[0]
|
34
|
+
if b != 0.0:
|
35
|
+
dx, dy = p2[0] - p1[0], p2[1] - p1[1]
|
36
|
+
c = np.sqrt(dx**2 + dy**2)
|
37
|
+
s = b * c/2
|
38
|
+
r = ((c/2)**2 + s**2)/2/s
|
39
|
+
g = np.arctan2(dx, dy)
|
40
|
+
a = 2*np.arctan(b)
|
41
|
+
pc = (p1[0] + r*np.sin(g - np.pi/2 + a),
|
42
|
+
p1[1] + r*np.cos(g - np.pi/2 + a))
|
43
|
+
if b < 0:
|
44
|
+
sa = np.arctan2(p2[1]-pc[1], p2[0]-pc[0])
|
45
|
+
ea = np.arctan2(p1[1]-pc[1], p1[0]-pc[0])
|
46
|
+
else:
|
47
|
+
sa = np.arctan2(p1[1]-pc[1], p1[0]-pc[0])
|
48
|
+
ea = np.arctan2(p2[1]-pc[1], p2[0]-pc[0])
|
49
|
+
logger.debug("Poly p1 %s p2 %s r %s", p1, p2, r)
|
50
|
+
yield Arc(Element(center=(pc[0], pc[1]),
|
51
|
+
radius=np.abs(r),
|
52
|
+
start_angle=sa/rf,
|
53
|
+
end_angle=ea/rf),
|
54
|
+
lf, rf,
|
55
|
+
xoff=xoff, yoff=yoff,
|
56
|
+
rotation=rotation)
|
57
|
+
else:
|
58
|
+
yield Line(Element(start=p1, end=p2), lf,
|
59
|
+
xoff=xoff, yoff=yoff,
|
60
|
+
rotation=rotation)
|
61
|
+
i += 1
|
62
|
+
|
63
|
+
|
64
|
+
def lw_polyline(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
|
65
|
+
"""returns a collection of bulged vertices
|
66
|
+
http://www.afralisp.net/archive/lisp/Bulges1.htm
|
67
|
+
"""
|
68
|
+
if isinstance(entity.points, list):
|
69
|
+
points = [(lf*p[0], lf*p[1]) for p in entity.points]
|
70
|
+
else:
|
71
|
+
points = [(lf*p[0], lf*p[1]) for p in entity.points()]
|
72
|
+
|
73
|
+
if points:
|
74
|
+
p1 = points[0]
|
75
|
+
for p2 in points[1:]:
|
76
|
+
yield Line(Element(start=p1, end=p2), lf,
|
77
|
+
xoff=xoff, yoff=yoff,
|
78
|
+
rotation=rotation)
|
79
|
+
p1 = p2
|
80
|
+
if entity.is_closed:
|
81
|
+
yield Line(Element(start=p1, end=points[0]), lf,
|
82
|
+
xoff=xoff, yoff=yoff,
|
83
|
+
rotation=rotation)
|
84
|
+
|
85
|
+
|
86
|
+
def ellipse(entity, lf, xoff=0.0, yoff=0.0, rotation=0.0):
|
87
|
+
w = np.linalg.norm(entity.major_axis) * 2
|
88
|
+
h = entity.ratio * w
|
89
|
+
theta = np.arctan2(entity.major_axis[1], entity.major_axis[0])
|
90
|
+
start_angle = entity.start_param
|
91
|
+
end_angle = entity.end_param
|
92
|
+
if end_angle < start_angle:
|
93
|
+
end_angle += 2*np.pi
|
94
|
+
alfa = np.linspace(start_angle, end_angle, 20)
|
95
|
+
x = 0.5 * w * np.cos(alfa)
|
96
|
+
y = 0.5 * h * np.sin(alfa)
|
97
|
+
R = np.array([
|
98
|
+
[np.cos(theta), -np.sin(theta)],
|
99
|
+
[np.sin(theta), np.cos(theta)]
|
100
|
+
])
|
101
|
+
x, y = np.dot(R, [x, y])
|
102
|
+
x += entity.center[0]
|
103
|
+
y += entity.center[1]
|
104
|
+
points = np.array((x, y)).T
|
105
|
+
p1 = points[0]
|
106
|
+
for p2 in points[1:]:
|
107
|
+
yield Line(Element(start=p1, end=p2), lf,
|
108
|
+
xoff=xoff, yoff=yoff,
|
109
|
+
rotation=rotation)
|
110
|
+
p1 = p2
|
111
|
+
|
112
|
+
|
113
|
+
def spline(entity, lf, min_dist=0.001, xoff=0.0, yoff=0.0, rotation=0.0):
|
114
|
+
if False:
|
115
|
+
yield Line(Element(start=entity.control_points[0],
|
116
|
+
end=entity.control_points[-1]), lf,
|
117
|
+
xoff=xoff, yoff=yoff,
|
118
|
+
rotation=rotation)
|
119
|
+
return
|
120
|
+
|
121
|
+
if False:
|
122
|
+
p_prev = None
|
123
|
+
for p in entity.control_points:
|
124
|
+
if p_prev:
|
125
|
+
yield Line(Element(start=p_prev, end=p), lf,
|
126
|
+
xoff=xoff, yoff=yoff,
|
127
|
+
rotation=rotation)
|
128
|
+
p_prev = p
|
129
|
+
return
|
130
|
+
|
131
|
+
points_between = entity.control_points[1:-1]
|
132
|
+
p1 = entity.control_points[0]
|
133
|
+
pe = entity.control_points[-1]
|
134
|
+
for p2 in points_between:
|
135
|
+
dist_12 = distance(p1, p2)
|
136
|
+
dist_2e = distance(p2, pe)
|
137
|
+
if dist_2e < min_dist:
|
138
|
+
logger.debug("SPLINE: ignor small end-distance %s", dist_2e)
|
139
|
+
yield Line(Element(start=p1, end=pe), lf,
|
140
|
+
xoff=xoff, yoff=yoff,
|
141
|
+
rotation=rotation)
|
142
|
+
return
|
143
|
+
|
144
|
+
if dist_12 > min_dist:
|
145
|
+
yield Line(Element(start=p1, end=p2), lf,
|
146
|
+
xoff=xoff, yoff=yoff,
|
147
|
+
rotation=rotation)
|
148
|
+
p1 = p2
|
149
|
+
else:
|
150
|
+
logger.debug("SPLINE: ignor small distance %s", dist_12)
|
151
|
+
|
152
|
+
yield Line(Element(start=p1, end=pe), lf,
|
153
|
+
xoff=xoff, yoff=yoff,
|
154
|
+
rotation=rotation)
|
155
|
+
|
156
|
+
|
157
|
+
def face3d(entity, lf):
|
158
|
+
logger.info("FACE3D: Points=%s", entity.points)
|
159
|
+
for i in range(len(entity.points)-1):
|
160
|
+
if not entity.is_edge_invisible(i):
|
161
|
+
ip = i+1 if i < 4 else 0
|
162
|
+
yield Line(Element(start=(entity.points[i][1],
|
163
|
+
entity.points[i][2]),
|
164
|
+
end=(entity.points[ip][1],
|
165
|
+
entity.points[ip][2])))
|
166
|
+
|
167
|
+
|
168
|
+
def insert_block(dwg, insert_entity, lf, rf, block, min_dist=0.001):
|
169
|
+
logger.debug('Insert %s entities from block %s',
|
170
|
+
len(block),
|
171
|
+
insert_entity.name)
|
172
|
+
logger.debug('Insert = %s', insert_entity.insert)
|
173
|
+
logger.debug('Rotation = %s', insert_entity.rotation)
|
174
|
+
logger.debug('Scale = %s', insert_entity.scale)
|
175
|
+
logger.debug('Rows = %s', insert_entity.row_count)
|
176
|
+
logger.debug('Cols = %s', insert_entity.col_count)
|
177
|
+
logger.debug('Row spacing = %s', insert_entity.row_spacing)
|
178
|
+
logger.debug('Col spacing = %s', insert_entity.col_spacing)
|
179
|
+
|
180
|
+
if insert_entity.insert != (0.0, 0.0, 0.0):
|
181
|
+
logger.debug('Different Location in Insert')
|
182
|
+
|
183
|
+
xoff = insert_entity.insert[0]
|
184
|
+
yoff = insert_entity.insert[1]
|
185
|
+
|
186
|
+
scale = (round(insert_entity.scale[0], 8),
|
187
|
+
round(insert_entity.scale[1], 8),
|
188
|
+
round(insert_entity.scale[2], 8))
|
189
|
+
if not (scale == (1.0, 1.0, 1.0) or
|
190
|
+
scale == (1.0, 1.0, 0.0)):
|
191
|
+
logger.error('Block scaling in Insert not supported')
|
192
|
+
logger.error(' scale = {}'.format(scale))
|
193
|
+
return
|
194
|
+
|
195
|
+
if(insert_entity.row_count > 1 or
|
196
|
+
insert_entity.col_count > 1 or
|
197
|
+
insert_entity.row_spacing > 0 or
|
198
|
+
insert_entity.col_spacing > 0):
|
199
|
+
logger.error('Multi Block references in Insert not supported')
|
200
|
+
return
|
201
|
+
|
202
|
+
for e in block:
|
203
|
+
if e.dxftype == 'ARC':
|
204
|
+
logger.debug("Block Arc")
|
205
|
+
yield Arc(e, lf, rf,
|
206
|
+
xoff=xoff, yoff=yoff,
|
207
|
+
rotation=insert_entity.rotation)
|
208
|
+
elif e.dxftype == 'CIRCLE':
|
209
|
+
logger.debug("Block Circle %s, Radius %f", e.center[:2], e.radius)
|
210
|
+
yield Circle(e, lf,
|
211
|
+
xoff=xoff, yoff=yoff,
|
212
|
+
rotation=insert_entity.rotation)
|
213
|
+
elif e.dxftype == 'LINE':
|
214
|
+
logger.debug("Block Line")
|
215
|
+
yield Line(e, lf,
|
216
|
+
xoff=xoff, yoff=yoff,
|
217
|
+
rotation=insert_entity.rotation)
|
218
|
+
elif e.dxftype == 'POLYLINE':
|
219
|
+
logger.debug("Block Polyline")
|
220
|
+
for p in polylines(e, lf, rf,
|
221
|
+
xoff=xoff, yoff=yoff,
|
222
|
+
rotation=insert_entity.rotation):
|
223
|
+
yield p
|
224
|
+
elif e.dxftype == 'LWPOLYLINE':
|
225
|
+
logger.debug("Block lwPolyline")
|
226
|
+
for p in lw_polyline(e, lf,
|
227
|
+
xoff=xoff, yoff=yoff,
|
228
|
+
rotation=insert_entity.rotation):
|
229
|
+
yield p
|
230
|
+
elif e.dxftype == 'SPLINE':
|
231
|
+
logger.debug("Block spline")
|
232
|
+
for l in spline(e, lf,
|
233
|
+
min_dist=min_dist,
|
234
|
+
xoff=xoff, yoff=yoff,
|
235
|
+
rotation=insert_entity.rotation):
|
236
|
+
yield l
|
237
|
+
elif e.dxftype == 'INSERT':
|
238
|
+
logger.debug("Nested Insert of Block %s", e.name)
|
239
|
+
block = dwg.blocks[e.name]
|
240
|
+
for l in insert_block(dwg, e, lf, rf, block, min_dist=min_dist):
|
241
|
+
yield l
|
242
|
+
|
243
|
+
else:
|
244
|
+
logger.warn("unknown type %s in block %s",
|
245
|
+
e.dxftype, insert_entity.name)
|
246
|
+
|
247
|
+
|
248
|
+
def dxfshapes0(dxffile, mindist=0.01, layers=[]):
|
249
|
+
"""returns a collection of dxf entities (ezdxf)"""
|
250
|
+
import ezdxf
|
251
|
+
dwg = ezdxf.readfile(dxffile)
|
252
|
+
id = 0
|
253
|
+
# $ACADVER: AC1006 = R10, AC1009 = R11 and R12, AC1012 = R13,
|
254
|
+
# AC1014 = R14 AC1015 = Release 2000/0i/2
|
255
|
+
# check units:
|
256
|
+
# dwg.header['$ANGDIR'] 1 = Clockwise angles, 0 = Counterclockwise
|
257
|
+
# dwg.header['$AUNITS'] 0 Decimal Degrees, 1 Deg/Min/Sec, 2 Grads, 3 Radians
|
258
|
+
# dwg.header['$INSUNIT'] 1 = Inches; 2 = Feet; 3 = Miles;
|
259
|
+
# 4 = Millimeters; 5 = Centimeters; 6 = Meters
|
260
|
+
# dwg.header['$LUNITS']
|
261
|
+
for e in dwg.modelspace():
|
262
|
+
if e.dxftype() == 'ARC':
|
263
|
+
yield Arc(e.dxf)
|
264
|
+
elif e.dxftype() == 'CIRCLE':
|
265
|
+
logger.debug("Circle %s, Radius %f", e.center[:2], e.radius)
|
266
|
+
yield Circle(e.dxf)
|
267
|
+
elif e.dxftype() == 'LINE':
|
268
|
+
yield Line(e.dxf)
|
269
|
+
elif e.dxftype() == 'POLYLINE':
|
270
|
+
for p in polylines(e):
|
271
|
+
yield p
|
272
|
+
elif e.dxftype() == 'SPLINE':
|
273
|
+
for l in spline(e, 1.0, in_dist=mindist):
|
274
|
+
yield l
|
275
|
+
elif e.dxftype() == 'POINT':
|
276
|
+
logger.debug("Id %d4: type %s ignored", id, e.dxftype)
|
277
|
+
else:
|
278
|
+
logger.warning("Id %d4: unknown type %s", id, e.dxftype)
|
279
|
+
id += 1
|
280
|
+
|
281
|
+
|
282
|
+
def dxfshapes(dxffile, mindist=0.01, layers=[]):
|
283
|
+
"""returns a collection of dxf entities (dxfgrabber)"""
|
284
|
+
import dxfgrabber
|
285
|
+
dwg = dxfgrabber.readfile(dxffile)
|
286
|
+
# print("Layers = {}".format(dwg.layers.names()))
|
287
|
+
id = 0
|
288
|
+
# $ACADVER: AC1006 = R10, AC1009 = R11 and R12, AC1012 = R13,
|
289
|
+
# AC1014 = R14 AC1015 = Release 2000/0i/2
|
290
|
+
# check units:
|
291
|
+
# dwg.header['$ANGDIR'] 1 = Clockwise angles, 0 = Counterclockwise
|
292
|
+
# dwg.header['$AUNITS'] Decimal Degrees, Deg/Min/Sec, Grads, Radians
|
293
|
+
# dwg.header['$INSUNIT'] 1 = Inches; 2 = Feet; 3 = Miles;
|
294
|
+
# 4 = Millimeters; 5 = Centimeters; 6 = Meters
|
295
|
+
# dwg.header['$LUNITS']
|
296
|
+
lf = 1
|
297
|
+
if dwg.header.get('$LUNITS', 0) == 1:
|
298
|
+
# conv = [1, 2.54e-2, 10.12, 633.0, 1e-3, 1e-2, 1]
|
299
|
+
lf = 2.54e3
|
300
|
+
|
301
|
+
rf = np.pi/180
|
302
|
+
if dwg.header.get('$AUNITS', 0) == 4:
|
303
|
+
rf = 1
|
304
|
+
|
305
|
+
for e in dwg.modelspace():
|
306
|
+
if not layers or e.layer in layers:
|
307
|
+
if e.dxftype == 'ARC':
|
308
|
+
yield Arc(e, lf, rf)
|
309
|
+
elif e.dxftype == 'CIRCLE':
|
310
|
+
logger.debug("Circle %s, Radius %f", e.center[:2], e.radius)
|
311
|
+
yield Circle(e, lf)
|
312
|
+
elif e.dxftype == 'LINE':
|
313
|
+
yield Line(e, lf)
|
314
|
+
elif e.dxftype == 'POLYLINE':
|
315
|
+
for p in polylines(e, lf, rf):
|
316
|
+
yield p
|
317
|
+
elif e.dxftype == 'LWPOLYLINE':
|
318
|
+
for p in lw_polyline(e, lf):
|
319
|
+
yield p
|
320
|
+
elif e.dxftype == 'SPLINE':
|
321
|
+
for l in spline(e, lf, min_dist=mindist):
|
322
|
+
yield l
|
323
|
+
elif e.dxftype == 'INSERT':
|
324
|
+
logger.debug("Insert of Block %s", e.name)
|
325
|
+
block = dwg.blocks[e.name]
|
326
|
+
for l in insert_block(dwg, e, lf, rf, block, min_dist=mindist):
|
327
|
+
yield l
|
328
|
+
elif e.dxftype == 'ELLIPSE':
|
329
|
+
for l in ellipse(e, lf):
|
330
|
+
yield l
|
331
|
+
#w = np.linalg.norm(e.major_axis) * 2
|
332
|
+
#h = e.ratio * w
|
333
|
+
#rtheta = np.arctan2(e.major_axis[1], e.major_axis[0])
|
334
|
+
#angle = rtheta*180/np.pi
|
335
|
+
#start_angle = e.start_param*180/np.pi + angle
|
336
|
+
#end_angle = e.end_param*180/np.pi + angle
|
337
|
+
#if end_angle < start_angle:
|
338
|
+
# end_angle += 360
|
339
|
+
#arc = Arc(Element(center=e.center,
|
340
|
+
# radius=w/2,
|
341
|
+
# start_angle=start_angle,
|
342
|
+
# end_angle=end_angle,
|
343
|
+
# width=w,
|
344
|
+
# height=h,
|
345
|
+
# rtheta=rtheta,
|
346
|
+
# start_param=e.start_param,
|
347
|
+
# end_param=e.end_param))
|
348
|
+
#yield arc
|
349
|
+
|
350
|
+
elif e.dxftype == 'POINT':
|
351
|
+
logger.debug("Id %d4: type %s ignored", id, e.dxftype)
|
352
|
+
elif e.dxftype == '3DFACE':
|
353
|
+
logger.warning(
|
354
|
+
"Id %d4: type %s not implemented", id, e.dxftype)
|
355
|
+
# for l in face3d(e, lf):
|
356
|
+
# yield l
|
357
|
+
else:
|
358
|
+
logger.warning("Id %d4: unknown type %s", id, e.dxftype)
|
359
|
+
id += 1
|
@@ -0,0 +1,78 @@
|
|
1
|
+
"""
|
2
|
+
Geom Parser for femm files
|
3
|
+
"""
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
from .shape import Arc, Line, Element
|
7
|
+
from .functions import distance, alpha_line, points_are_close
|
8
|
+
|
9
|
+
fem_points = []
|
10
|
+
|
11
|
+
|
12
|
+
def read_fem_points(f, num):
|
13
|
+
for x in range(num):
|
14
|
+
p = f.readline().split()
|
15
|
+
fem_points.append([float(p[0]), float(p[1])])
|
16
|
+
|
17
|
+
|
18
|
+
def read_fem_lines(f, num):
|
19
|
+
for x in range(num):
|
20
|
+
p = f.readline().split()
|
21
|
+
i1 = int(p[0])
|
22
|
+
i2 = int(p[1])
|
23
|
+
p1 = fem_points[i1]
|
24
|
+
p2 = fem_points[i2]
|
25
|
+
if points_are_close(p1, p2):
|
26
|
+
logger.warning("FEMM: Line with points close together")
|
27
|
+
logger.warning(" p1 = %s, p2 =%s", p1, p2)
|
28
|
+
yield Line(Element(start=p1, end=p2))
|
29
|
+
|
30
|
+
|
31
|
+
def read_fem_arcs(f, num):
|
32
|
+
for x in range(num):
|
33
|
+
p = f.readline().split()
|
34
|
+
i1 = int(p[0])
|
35
|
+
i2 = int(p[1])
|
36
|
+
alpha = float(p[2])
|
37
|
+
p1 = fem_points[i1]
|
38
|
+
p2 = fem_points[i2]
|
39
|
+
if points_are_close(p1, p2):
|
40
|
+
logger.warning("FEMM: Arc with points close together")
|
41
|
+
logger.warning(" p1 = %s, p2 = %s", p1, p2)
|
42
|
+
for e in get_fem_arc(p1, p2, alpha):
|
43
|
+
yield e
|
44
|
+
|
45
|
+
|
46
|
+
def get_fem_arc(pA, pB, alfa):
|
47
|
+
alpha = alfa/180.0*np.pi/2.0
|
48
|
+
y = distance(pA, pB) / 2.0
|
49
|
+
x = y / np.tan(alpha)
|
50
|
+
r = np.sqrt(x**2 + y**2)
|
51
|
+
|
52
|
+
delta = alpha_line(pA, pB)
|
53
|
+
|
54
|
+
c = [pA[0] + y, pA[1] + x]
|
55
|
+
phi = alpha_line(pA, c) + delta
|
56
|
+
pC = point_on_arc(pA, r, phi)
|
57
|
+
|
58
|
+
startangle = alpha_line(pC, pA)
|
59
|
+
endangle = alpha_line(pC, pB)
|
60
|
+
yield Arc(Element(center=pC,
|
61
|
+
radius=r,
|
62
|
+
start_angle=startangle*180/np.pi,
|
63
|
+
end_angle=endangle*180/np.pi))
|
64
|
+
|
65
|
+
|
66
|
+
def femshapes(femfile):
|
67
|
+
f = open(femfile, 'r')
|
68
|
+
|
69
|
+
for data in f:
|
70
|
+
text = data.split()
|
71
|
+
if text[0] == '[NumPoints]':
|
72
|
+
read_fem_points(f, int(text[2]))
|
73
|
+
elif text[0] == '[NumSegments]':
|
74
|
+
for e in read_fem_lines(f, int(text[2])):
|
75
|
+
yield e
|
76
|
+
elif text[0] == '[NumArcSegments]':
|
77
|
+
for e in read_fem_arcs(f, int(text[2])):
|
78
|
+
yield e
|