femagtools 1.6.8__py3-none-any.whl → 1.7.1__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.
Files changed (51) hide show
  1. femagtools/__init__.py +2 -2
  2. femagtools/bch.py +1 -1
  3. femagtools/dxfsl/area.py +343 -406
  4. femagtools/dxfsl/areabuilder.py +139 -12
  5. femagtools/dxfsl/conv.py +27 -9
  6. femagtools/dxfsl/converter.py +406 -127
  7. femagtools/dxfsl/corner.py +3 -0
  8. femagtools/dxfsl/femparser.py +1 -1
  9. femagtools/dxfsl/fslrenderer.py +290 -246
  10. femagtools/dxfsl/functions.py +4 -2
  11. femagtools/dxfsl/geom.py +1204 -893
  12. femagtools/dxfsl/journal.py +58 -22
  13. femagtools/dxfsl/machine.py +254 -75
  14. femagtools/dxfsl/plotrenderer.py +38 -3
  15. femagtools/dxfsl/shape.py +380 -103
  16. femagtools/dxfsl/symmetry.py +679 -110
  17. femagtools/femag.py +27 -2
  18. femagtools/forcedens.py +65 -40
  19. femagtools/fsl.py +71 -28
  20. femagtools/losscoeffs.py +46 -0
  21. femagtools/machine/effloss.py +8 -1
  22. femagtools/machine/im.py +3 -1
  23. femagtools/machine/pm.py +11 -7
  24. femagtools/machine/sizing.py +15 -12
  25. femagtools/machine/sm.py +114 -33
  26. femagtools/machine/utils.py +38 -34
  27. femagtools/model.py +12 -2
  28. femagtools/moo/population.py +1 -1
  29. femagtools/parstudy.py +17 -1
  30. femagtools/plot/__init__.py +1 -1
  31. femagtools/plot/char.py +24 -7
  32. femagtools/plot/forcedens.py +56 -29
  33. femagtools/plot/mcv.py +4 -1
  34. femagtools/plot/phasor.py +6 -1
  35. femagtools/poc.py +17 -10
  36. femagtools/templates/cogg_calc.mako +7 -1
  37. femagtools/templates/displ_stator_rotor.mako +33 -0
  38. femagtools/templates/fieldcalc.mako +10 -16
  39. femagtools/templates/pm_sym_f_cur.mako +1 -1
  40. femagtools/tks.py +3 -9
  41. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/LICENSE +1 -0
  42. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/METADATA +7 -4
  43. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/RECORD +51 -50
  44. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/WHEEL +1 -1
  45. tests/engines/__init__.py +0 -20
  46. tests/geom/__init__.py +0 -20
  47. tests/moo/__init__.py +0 -20
  48. tests/test_model.py +8 -1
  49. tests/test_sizing.py +2 -2
  50. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/entry_points.txt +0 -0
  51. {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/area.py CHANGED
@@ -15,8 +15,8 @@ from .functions import less_equal, less, greater_equal, greater
15
15
  from .functions import distance, alpha_angle, alpha_line, min_angle, max_angle
16
16
  from .functions import point, line_m, line_n, intersect_point, points_are_close
17
17
  from .functions import middle_angle, part_of_circle, is_same_angle
18
- from .functions import area_size
19
- from .shape import Element, Shape, Line, Arc, Circle, is_Circle
18
+ from .functions import area_size, normalise_angle, positive_angle
19
+ from .shape import Element, Shape, Line, Arc, Circle, is_Circle, is_Line, is_Arc
20
20
 
21
21
  logger = logging.getLogger('femagtools.area')
22
22
 
@@ -27,11 +27,26 @@ logger = logging.getLogger('femagtools.area')
27
27
 
28
28
  area_number = 0
29
29
 
30
+ TYPE_AIR = 0
31
+ TYPE_IRON = 1
32
+ TYPE_WINDINGS = 2
33
+ TYPE_MAGNET_AIRGAP = 3
34
+ TYPE_MAGNET_RECT = 4
35
+ TYPE_YOKE = 5
36
+ TYPE_TOOTH = 6
37
+ TYPE_MAGNET_OR_AIR = 8
38
+ TYPE_AIR_OR_IRON = 9
39
+ TYPE_MAGNET_OR_IRON = 9
40
+ TYPE_SHAFT = 10
41
+ TYPE_MAGNET_RECT_NEAR_AIRGAP = 11
42
+ TYPE_WINDINGS_OR_AIR = 12
43
+ TYPE_MAGNET_UNDEFINED = 99
44
+ TYPE_GROUP = 20
30
45
 
31
46
  class Area(object):
32
47
  def __init__(self, area, center, sym_tolerance):
33
48
  self.area = area
34
- self.type = 0 # material
49
+ self.type = -1 # material
35
50
  self.phi = 0.0
36
51
  self.min_angle = 0.0
37
52
  self.max_angle = 0.0
@@ -43,9 +58,13 @@ class Area(object):
43
58
  self.close_to_startangle = False
44
59
  self.close_to_endangle = False
45
60
  self.mag_rectangle = False
61
+ self.mag_width = 0.0
46
62
  self.min_dist = 99999.0
47
63
  self.max_dist = 0.0
48
- self.minmax_xy = [0,0,0,0]
64
+ self.min_x = None
65
+ self.max_x = None
66
+ self.min_y = None
67
+ self.max_y = None
49
68
  self.height = 0.0
50
69
  self.alpha = 0.0
51
70
  self.count = 1
@@ -62,7 +81,9 @@ class Area(object):
62
81
  global area_number
63
82
  area_number += 1
64
83
  self.id = area_number
84
+ self.is_child = False
65
85
  self.areas_inside = {}
86
+ self.areas_of_group = []
66
87
 
67
88
  def identifier(self):
68
89
  return "{}-{}".format(self.id, self.type)
@@ -180,88 +201,94 @@ class Area(object):
180
201
  last_point = next_nodes[-1]
181
202
 
182
203
  def legend(self):
183
- if self.type == 1:
204
+ if self.type == TYPE_IRON:
184
205
  return 'Iron'
185
- if self.type == 2:
206
+ if self.type == TYPE_WINDINGS:
186
207
  return 'Windings'
187
- if self.type == 3 or self.type == 4:
208
+ if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
188
209
  return 'Magnet'
189
- if self.type == 5:
210
+ if self.type == TYPE_YOKE:
190
211
  return 'Yoke'
191
- if self.type == 6:
212
+ if self.type == TYPE_TOOTH:
192
213
  return 'Tooth'
193
- if self.type == 10:
214
+ if self.type == TYPE_SHAFT:
194
215
  return 'Shaft'
195
216
  return ''
196
217
 
197
218
  def name(self):
198
- if self.type == 1:
219
+ if self.type == TYPE_IRON:
199
220
  return 'Iron'
200
- if self.type == 2:
221
+ if self.type == TYPE_WINDINGS:
201
222
  return 'Wndg'
202
- if self.type == 3 or self.type == 4:
223
+ if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
203
224
  return 'Mag'
204
- if self.type == 5:
225
+ if self.type == TYPE_YOKE:
205
226
  return 'StJo'
206
- if self.type == 6:
227
+ if self.type == TYPE_TOOTH:
207
228
  return 'StZa'
208
- if self.type == 10:
229
+ if self.type == TYPE_SHAFT:
209
230
  return 'Shft'
210
231
  return ''
211
232
 
212
233
  def color(self):
213
- if self.type == 1:
234
+ if self.type == TYPE_IRON:
214
235
  return 'cyan'
215
- if self.type == 2:
236
+ if self.type == TYPE_WINDINGS:
216
237
  return 'green'
217
- if self.type == 3 or self.type == 4:
238
+ if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
218
239
  return 'red'
219
- if self.type == 5:
240
+ if self.type == TYPE_YOKE:
220
241
  return 'cyan'
221
- if self.type == 6:
242
+ if self.type == TYPE_TOOTH:
222
243
  return 'skyblue'
223
- if self.type == 10:
244
+ if self.type == TYPE_SHAFT:
224
245
  return 'lightgrey'
225
246
  return 'white'
226
247
 
227
248
  def color_alpha(self):
228
- if self.type == 1:
249
+ if self.type == TYPE_IRON:
229
250
  return 0.3
230
- if self.type == 2:
251
+ if self.type == TYPE_WINDINGS:
231
252
  return 1.0
232
- if self.type == 3 or self.type == 4:
253
+ if self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT:
233
254
  return 1.0
234
- if self.type == 5:
255
+ if self.type == TYPE_YOKE:
235
256
  return 0.5
236
- if self.type == 6:
257
+ if self.type == TYPE_TOOTH:
237
258
  return 1.0
238
- if self.type == 10:
259
+ if self.type == TYPE_SHAFT:
239
260
  return 0.8
240
261
  return 1.0
241
262
 
242
263
  def is_iron(self):
243
- return self.type == 1 or self.type == 5 or self.type == 6
264
+ return \
265
+ self.type == TYPE_IRON or \
266
+ self.type == TYPE_YOKE or \
267
+ self.type == TYPE_TOOTH
244
268
 
245
269
  def is_stator_iron_yoke(self):
246
- return self.type == 5
270
+ return self.type == TYPE_YOKE
247
271
 
248
272
  def is_stator_iron_tooth(self):
249
- return self.type == 6
273
+ return self.type == TYPE_TOOTH
250
274
 
251
275
  def is_rotor_iron(self):
252
- return self.type == 1
276
+ return self.type == TYPE_IRON
253
277
 
254
278
  def is_winding(self):
255
- return self.type == 2
279
+ return self.type == TYPE_WINDINGS
256
280
 
257
281
  def is_magnet(self):
258
- return self.type == 3 or self.type == 4
282
+ return self.type == TYPE_MAGNET_AIRGAP or self.type == TYPE_MAGNET_RECT
259
283
 
260
284
  def is_shaft(self):
261
- return self.type == 10
285
+ return self.type == TYPE_SHAFT
262
286
 
263
287
  def is_air(self):
264
- return self.type == 0
288
+ return self.type == TYPE_AIR
289
+
290
+ def is_type(self, type):
291
+ return self.type == type
265
292
 
266
293
  def set_type(self, t):
267
294
  self.type = t
@@ -270,7 +297,7 @@ class Area(object):
270
297
  if not self.area:
271
298
  return
272
299
 
273
- self.minmax_xy = self.minmax()
300
+ self.min_x, self.max_x, self.min_y, self.max_y = self.minmax()
274
301
  s = self.area[0]
275
302
  mm_angle = s.minmax_angle_from_center(center)
276
303
  self.min_angle = mm_angle[0]
@@ -289,8 +316,10 @@ class Area(object):
289
316
  self.alpha = round(alpha_angle(self.min_angle, self.max_angle), 3)
290
317
 
291
318
  def center_is_inside(self, center):
292
- if self.minmax_xy[0] < center[0] and self.minmax_xy[1] > center[0] and \
293
- self.minmax_xy[2] < center[1] and self.minmax_xy[3] > center[1]:
319
+ if less(self.min_x, center[0], rtol=1e-03, atol=1e-04) and \
320
+ greater(self.max_x, center[0], rtol=1e-03, atol=1e-04) and \
321
+ less(self.min_y, center[1], rtol=1e-03, atol=1e-04) and \
322
+ greater(self.max_y, center[1], rtol=1e-03, atol=1e-04):
294
323
  return True
295
324
  return False
296
325
 
@@ -329,9 +358,8 @@ class Area(object):
329
358
  return False
330
359
 
331
360
  line = Line(Element(start=p1, end=p2))
332
- plist = self.intersect_points(line)
361
+ plist = self.get_intersect_points(line)
333
362
  points = len(plist)
334
- plist.sort()
335
363
 
336
364
  aux_lines = [e for e in self.area if e.has_attribute('auxline')]
337
365
  if aux_lines:
@@ -358,6 +386,15 @@ class Area(object):
358
386
  def is_touching_both_sides(self):
359
387
  return (self.close_to_startangle and self.close_to_endangle)
360
388
 
389
+ def is_in_touch_with_area(self, geom, a):
390
+ n1 = self.area[0].n1
391
+ n2 = a.area[0].n2
392
+ try:
393
+ return nx.has_path(geom.g, n1, n2)
394
+ except nx.NetworkXError:
395
+ logger.warning("has_path() failed")
396
+ return False
397
+
361
398
  def has_connection(self, geom, a, ndec):
362
399
  assert(self.area)
363
400
  assert(a.area)
@@ -395,12 +432,14 @@ class Area(object):
395
432
  d = distance(p1, p2)
396
433
  gap_list.append((d, (p1, p2), dist_id, a.get_id()))
397
434
 
398
- d, p1, p2 = a.get_nearest_point(center, radius, rightangle)
399
- if p1:
400
- gap_list.append((d, (p1, p2), dist_id, a.get_id()))
401
- d, p1, p2 = a.get_nearest_point(center, radius, leftangle)
402
- if p1:
403
- gap_list.append((d, (p1, p2), dist_id, a.get_id()))
435
+ if rightangle is not None:
436
+ d, p1, p2 = a.get_nearest_point(center, radius, rightangle)
437
+ if p1:
438
+ gap_list.append((d, (p1, p2), dist_id, a.get_id()))
439
+ if leftangle is not None:
440
+ d, p1, p2 = a.get_nearest_point(center, radius, leftangle)
441
+ if p1:
442
+ gap_list.append((d, (p1, p2), dist_id, a.get_id()))
404
443
  if not gap_list:
405
444
  return []
406
445
  gap_list.sort()
@@ -635,11 +674,21 @@ class Area(object):
635
674
  return True
636
675
  return False
637
676
 
638
- def intersect_points(self, line):
677
+ def get_intersect_points(self, line, rtol=1.e-4, atol=1e-3):
639
678
  points = []
640
679
  for e in self.area:
641
- points += e.intersect_line(line, include_end=True)
642
- return points
680
+ points += e.intersect_line(line, rtol=rtol, atol=atol, include_end=True)
681
+ if not points:
682
+ return []
683
+ points = [(x, y) for x, y in points]
684
+ points.sort()
685
+ p1 = points[0]
686
+ pts = [p1]
687
+ for p2 in points[1:]:
688
+ if not points_are_close(p1, p2, rtol=rtol, atol=atol):
689
+ pts.append(p2)
690
+ p1 = p2
691
+ return pts
643
692
 
644
693
  def is_point_inside(self, pt):
645
694
  for e in self.area:
@@ -647,14 +696,49 @@ class Area(object):
647
696
  return True
648
697
  return False
649
698
 
699
+ def the_area_is_inside_area(self, a):
700
+ p = a.area[0].n1
701
+ return self.the_point_is_inside_area(p)
702
+
703
+ def the_point_is_inside_area(self, p):
704
+ x, y = p
705
+ if less_equal(x, self.min_x) or greater_equal(x, self.max_x):
706
+ return False
707
+ if less_equal(y, self.min_y) or greater_equal(y, self.max_y):
708
+ return False
709
+
710
+ p1 = (self.min_x - 5, y)
711
+ p2 = (self.max_x + 5, y)
712
+ line = Line(Element(start=p1, end=p2))
713
+ pts = self.get_intersect_points(line)
714
+ if len(pts) % 2 != 0:
715
+ return False
716
+
717
+ c = 0
718
+ for ax, ay in pts:
719
+ if not less(ax, x):
720
+ if c % 2 != 1:
721
+ return False
722
+ break
723
+ c += 1
724
+
725
+ if not c < len(pts):
726
+ return False
727
+
728
+ ax, ay = pts[c]
729
+ if not less(x, ax):
730
+ return False
731
+ return True
732
+
650
733
  def get_best_point_inside(self, geom):
651
- mm = self.minmax_xy
652
- px1 = mm[0]-5
653
- px2 = mm[1]+5
734
+ px1 = self.min_x - 5
735
+ px2 = self.max_x + 5
654
736
 
655
- y_dist = mm[3] - mm[2]
737
+ y_dist = self.max_y - self.min_y
656
738
  step = y_dist / 6
657
- y_list = np.arange(mm[2] + step*0.3, mm[3] - step*0.3, step)
739
+ y_list = np.arange(self.min_y + step * 0.3,
740
+ self.max_y - step * 0.3,
741
+ step)
658
742
 
659
743
  lines = []
660
744
  for y in y_list:
@@ -745,10 +829,9 @@ class Area(object):
745
829
 
746
830
  def get_point_inside(self, geom):
747
831
  """return point inside area"""
748
- mm = self.minmax_xy
749
- y = (mm[2]+mm[3])/2
750
- p1 = (mm[0]-5, y)
751
- p2 = (mm[1]+5, y)
832
+ y = (self.min_y + self.max_y) / 2
833
+ p1 = (self.min_x - 5, y)
834
+ p2 = (self.max_x + 5, y)
752
835
  line = Line(Element(start=p1, end=p2))
753
836
 
754
837
  points = []
@@ -820,6 +903,32 @@ class Area(object):
820
903
  renderer.fill(x, y, color, alpha)
821
904
  return True
822
905
 
906
+ def magnet_arrow_length(self):
907
+ if self.is_type(TYPE_MAGNET_AIRGAP):
908
+ return (self.max_dist - self.min_dist) * 0.9
909
+ if self.is_type(TYPE_MAGNET_RECT):
910
+ return self.mag_width
911
+ return 0.0
912
+
913
+ def render_magnet_phi(self, renderer, length):
914
+ if not self.is_magnet():
915
+ return
916
+ p1 = None
917
+ p2 = None
918
+ if self.is_type(TYPE_MAGNET_AIRGAP):
919
+ mid = middle_angle(self.min_angle, self.max_angle)
920
+ d = self.min_dist + (self.max_dist - self.min_dist) * 0.3
921
+ p1 = point((0.0, 0.0), d, mid)
922
+ if self.is_type(TYPE_MAGNET_RECT):
923
+ x = self.min_x + (self.max_x - self.min_x) / 2
924
+ y = self.min_y + (self.max_y - self.min_y) / 2
925
+ p1 = (x, y)
926
+ if p1 is None:
927
+ return
928
+ p2 = point(p1, length, self.phi)
929
+ renderer.arrow(p1, p2, linewidth=1.2)
930
+ return
931
+
823
932
  def render_legend(self, renderer):
824
933
  return renderer.new_legend_handle(self.color(),
825
934
  self.color_alpha(),
@@ -867,25 +976,16 @@ class Area(object):
867
976
  return False
868
977
  return True
869
978
 
870
- def has_round_edges(self):
871
- arcs = 0
872
- for e in self.area:
873
- # if isinstance(e, Line):
874
- # if not np.isclose(angle, alpha_line(center, e.p1)):
875
- # return False
876
- # if not np.isclose(angle, alpha_line(center, e.p2)):
877
- # return False
878
- if isinstance(e, Arc):
879
- arcs += 1
880
-
881
- return arcs > 0
882
-
883
979
  def is_shaft_area(self, center):
884
980
  logger.debug("Begin of check shaft")
885
981
 
886
- if not self.is_touching_both_sides():
887
- logger.debug("End of check shaft: don't touch both sides")
888
- return False
982
+ #if not self.is_touching_both_sides():
983
+ # logger.debug("End of check shaft: don't touch both sides")
984
+ # return False
985
+
986
+ if np.isclose(0.0, self.min_dist, rtol=1e-6, atol=1e-4):
987
+ logger.debug("End of check shaft: ok (node in center)")
988
+ return True
889
989
 
890
990
  for n in self.list_of_nodes():
891
991
  a = alpha_line(center, n)
@@ -900,247 +1000,143 @@ class Area(object):
900
1000
  continue
901
1001
  logger.debug("End of check shaft: no")
902
1002
  return False
1003
+
903
1004
  logger.debug("End of check shaft: ok")
904
1005
  return True
905
1006
 
906
- def is_rectangle(self):
907
- lines = [[c, e.m(99999.0), e.length()]
908
- for c, e in enumerate(self.area)
909
- if isinstance(e, Line)]
910
- lines.sort()
911
-
912
- line_count = 1
913
- m_first = 0.0
914
- m_prev = 999.999999
915
- c_prev = -99
916
- m_all = []
917
- for c, m, l in lines:
918
- if c_prev >= 0:
919
- if np.isclose(m_prev, m, atol=0.001):
920
- if c_prev+1 != c:
921
- # Gleiche Steigung, aber keine Verlängerung
922
- line_count += 1
923
- m_all.append(m_prev)
924
- else:
925
- line_count += 1
926
- m_all.append(m_prev)
927
- else:
928
- m_first = m
1007
+ def get_magnet_line_angles(self):
1008
+ lines = [e for e in self.area if is_Line(e)]
1009
+ if len(lines) < 4:
1010
+ logger.debug("get_magnet_line_angles: only %s lines", len(lines))
1011
+ return []
929
1012
 
930
- m_prev = m
931
- c_prev = c
1013
+ angles = []
1014
+ prev_angle = lines[0].get_positive_angle()
1015
+ logger.debug("first angle = %s", prev_angle)
1016
+ prev_length = lines[0].length()
932
1017
 
933
- m_all.append(m_prev)
1018
+ for line in lines[1:]:
1019
+ this_angle = line.get_positive_angle()
1020
+ logger.debug("next angle = %s", this_angle)
1021
+ this_length = line.length()
934
1022
 
935
- if np.isclose(m_prev, m_first, atol=0.001):
936
- line_count -= 1
1023
+ if np.isclose(prev_angle, this_angle, rtol=1e-04, atol=1e-02):
1024
+ # same direction
1025
+ prev_length += this_length
1026
+ else:
1027
+ angles.append((prev_length, prev_angle))
1028
+ prev_angle = this_angle
1029
+ prev_length = this_length
937
1030
 
938
- if line_count == 4:
939
- logger.debug("is_rectangle: m={}".format(m_all))
940
- if not np.isclose(m_all[0], m_all[2], atol=0.001):
941
- return False
942
- if not np.isclose(m_all[1], m_all[3], atol=0.001):
943
- return False
944
- return True
1031
+ if not angles:
1032
+ logger.debug("get_magnet_line_angles: only one angle")
1033
+ return []
945
1034
 
946
- return False
1035
+ this_length, this_angle = angles[0]
1036
+ if not np.isclose(prev_angle, this_angle, rtol=1e-04, atol=1e-02):
1037
+ angles.append((prev_length, prev_angle))
1038
+ else:
1039
+ prev_length += this_length
1040
+ angles[0] = (prev_length, prev_angle)
947
1041
 
948
- def is_mag_rectangle(self):
949
- lines_ceml = [[c, e, e.m(99999.0), e.length()]
950
- for c, e in enumerate(self.area)]
951
- # c = Count
952
- # e = Element
953
- # m = Steigung
954
- # l = Länge
955
- # L = class Line
956
- if len(lines_ceml) < 4:
957
- return False
1042
+ l, first_angle = angles[0]
1043
+ l, last_angle = angles[-1]
1044
+ if np.isclose(first_angle, last_angle, rtol=1e-04, atol=1e-02):
1045
+ del angles[-1]
1046
+ return angles
958
1047
 
959
- logger.debug("=== BEGIN OF is_mag_rectangle() [{} lines]"
960
- .format(len(lines_ceml)))
961
-
962
- c_prev = lines_ceml[0][0]
963
- a_prev = 999
964
- p = None
965
-
966
- e0 = lines_ceml[0][1]
967
- e0_p1 = e0.p1
968
- e0_p2 = e0.p2
969
- L_prev = isinstance(e0, Line)
970
- l_prev = lines_ceml[0][3]
971
- m_prev = lines_ceml[0][2]
972
-
973
- e1 = lines_ceml[1][1]
974
- e1_p1 = e1.p1
975
- e1_p2 = e1.p2
976
-
977
- if (points_are_close(e0_p2, e1_p1, atol=1e-02) or
978
- points_are_close(e0_p2, e1_p2, atol=1e-02)):
979
- a_prev = alpha_line(e0_p1, e0_p2)
980
- p = e0_p2
981
- elif (points_are_close(e0_p1, e1_p1, atol=1e-02) or
982
- points_are_close(e0_p1, e1_p2, atol=1e-02)):
983
- a_prev = alpha_line(e0_p2, e0_p1)
984
- p = e0_p1
985
- else:
986
- logger.error(
987
- "ERROR: is_mag_rectangle(): points are not close together")
988
- logger.error(" e0 p1={}, p2={}".format(e0_p1, e0_p2))
989
- logger.error(" e1 p1={}, p2={}".format(e1_p1, e1_p2))
990
- return False
1048
+ def get_magnet_phi(self, angles):
1049
+ if not angles:
1050
+ return 0.0
991
1051
 
992
- def alpha_current(p, e):
993
- if points_are_close(p, e.p1, atol=1e-02):
994
- return e.p2, alpha_line(e.p1, e.p2), isinstance(e, Line)
995
- if points_are_close(p, e.p2, atol=1e-02):
996
- return e.p1, alpha_line(e.p2, e.p1), isinstance(e, Line)
997
- logger.error(
998
- "ERROR: is_mag_rectangle(): points are not close together")
999
- logger.error(" p={}, p1={}, p2={}".format(p, e.p1, e.p2))
1000
- return None, None, False
1001
-
1002
- lines_clamL = []
1003
- for c, e, m, l in lines_ceml[1:]:
1004
- p, a_curr, L_curr = alpha_current(p, e)
1005
- if not p:
1006
- return False
1052
+ angles.sort(reverse=True)
1053
+ # calculate orientation (no rectangle check)
1054
+ l, alpha = angles[0]
1055
+ phi = normalise_angle(alpha + np.pi/2)
1056
+ logger.debug("alpha = %s, phi = %s", alpha, phi)
1007
1057
 
1008
- if is_same_angle(a_prev, a_curr, atol=0.01):
1009
- # its the same angle and both are Lines
1010
- # assert(np.isclose(m_prev, m, atol=0.001))
1011
- if c_prev+1 != c:
1012
- logger.debug(" - ok, but not an extension")
1013
- # ..., but not an extension
1014
- lines_clamL.append([c_prev, l_prev, a_prev, m])
1015
- l_prev = e.length()
1016
- else:
1017
- # ... and an extension
1018
- l_prev += e.length()
1019
- logger.debug(" - ok, it's an extension")
1020
- else:
1021
- # it's a different angle
1022
- logger.debug(" - diff, angle {} and {} not equal "
1023
- .format(a_prev, a_curr))
1024
- lines_clamL.append([c_prev, l_prev, a_prev, m_prev, L_prev])
1025
- l_prev = e.length()
1026
-
1027
- a_prev = a_curr
1028
- L_prev = L_curr
1029
- m_prev = m
1030
- c_prev = c
1031
-
1032
- lines_clamL.append([c_prev, l_prev, a_prev, m_prev, L_prev])
1033
- if np.isclose(lines_clamL[0][2], lines_clamL[-1][2], atol=0.001):
1034
- # Gleicher Winkel am Anfang und am Ende
1035
- lines_clamL[0][1] += lines_clamL[-1][1] # length
1036
- del lines_clamL[-1]
1037
- logger.debug(" > last entry deleted")
1038
-
1039
- if len(lines_clamL) < 4:
1040
- logger.debug("=== END OF is_mag_rectangle(): NO RECTANGLE #1")
1041
- return False
1058
+ mid = middle_angle(self.min_angle, self.max_angle)
1059
+ angle = alpha_angle(mid, phi)
1060
+ logger.debug("phi=%s, mid=%s, angle=%s", phi, mid, angle)
1042
1061
 
1043
- lines_lmcL = [[l, m, c, L] for c, l, a, m, L in lines_clamL]
1044
- lines_lmcL.sort(reverse=True)
1045
-
1046
- if not np.isclose(lines_lmcL[0][1], lines_lmcL[1][1], atol=0.05):
1047
- # Die Steigungen der zwei längsten Linien müssen gleich sein
1048
- logger.debug("--- m %s <> %s ---",
1049
- lines_lmcL[0][1],
1050
- lines_lmcL[1][1])
1051
- logger.debug("--- l %s, %s, %s ---",
1052
- lines_lmcL[0][0],
1053
- lines_lmcL[1][0],
1054
- lines_lmcL[2][0])
1055
- logger.debug("=== END OF is_mag_rectangle(): NO RECTANGLE #2")
1056
- return False
1062
+ if greater(angle, np.pi * 0.5, rtol=1e-5) and \
1063
+ less(angle, np.pi * 1.5, rtol=1e-5):
1064
+ phi = normalise_angle(phi + np.pi)
1057
1065
 
1058
- def excursion_to_same_direction(clam):
1059
- if len(clam) < 4:
1060
- return False
1066
+ logger.debug("phi of magnet %s is %s", self.identifier(), phi)
1067
+ return phi
1061
1068
 
1062
- alpha = alpha_angle(clam[0][2], clam[1][2])
1063
- clockwise = not alpha < np.pi
1069
+ def get_magnet_orientation(self):
1070
+ logger.debug("get magnet orientation for %s", self.identifier())
1071
+ if self.is_type(TYPE_MAGNET_RECT):
1072
+ angles = self.get_magnet_line_angles()
1073
+ return self.get_magnet_phi(angles)
1064
1074
 
1065
- angle_prev = clam[1][2]
1066
- for c, l, angle_curr, m, t in clam[2:]:
1067
- alpha = alpha_angle(angle_prev, angle_curr)
1068
- if clockwise:
1069
- if alpha < np.pi:
1070
- return False
1075
+ if self.is_type(TYPE_MAGNET_AIRGAP):
1076
+ if self.close_to_endangle:
1077
+ if self.close_to_startangle:
1078
+ return middle_angle(self.min_angle, self.max_angle)
1071
1079
  else:
1072
- if alpha > np.pi:
1073
- return False
1074
- angle_prev = angle_curr
1075
- return True # end of all_lines_with_same_direction()
1080
+ return self.max_angle
1081
+ return middle_angle(self.min_angle, self.max_angle)
1076
1082
 
1077
- lines_cmL = [[c, m, L] for l, m, c, L in lines_lmcL[0:4]]
1078
- lines_cmL.sort()
1083
+ return 0.0
1079
1084
 
1080
- if np.isclose(lines_cmL[0][1], lines_cmL[2][1], atol=0.001):
1081
- if not (lines_cmL[0][2] and lines_cmL[2][2]):
1082
- logger.debug("=== END OF is_mag_rectangle(): not 2 lines #1")
1083
- return False
1084
- ok = excursion_to_same_direction(lines_clamL)
1085
- logger.debug("=== END OF is_mag_rectangle(): OK = {} #1"
1086
- .format(ok))
1087
- return ok
1088
- if np.isclose(lines_cmL[1][1], lines_cmL[3][1], atol=0.001):
1089
- if not (lines_cmL[1][2] and lines_cmL[3][2]):
1090
- logger.debug("=== END OF is_mag_rectangle(): not 2 lines #2")
1091
- return False
1085
+ def is_magnet_rectangle(self):
1086
+ angles = self.get_magnet_line_angles()
1092
1087
 
1093
- ok = excursion_to_same_direction(lines_clamL)
1094
- logger.debug("=== END OF is_mag_rectangle(): OK = {} #2"
1095
- .format(ok))
1096
- return ok
1088
+ if len(angles) != 4:
1089
+ logger.debug("is_magnet_rectangle: %s angles, not 4", len(angles))
1090
+ return False
1097
1091
 
1098
- logger.debug("=== END OF is_mag_rectangle(): NO RECTANGLE #3")
1099
- return False
1092
+ for l, a in angles:
1093
+ logger.debug("+ magnet_rectangle: alpha=%s, length=%s", a, l)
1100
1094
 
1101
- def get_mag_orient_rectangle(self):
1102
- lines = [[e.m(99999.0), e.length(), alpha_line(e.p1, e.p2)]
1103
- for e in self.area
1104
- if isinstance(e, Line)]
1105
- lines.sort()
1106
-
1107
- m_prev = 999.999999
1108
- a_prev = 0.0
1109
- l_total = 0.0
1110
- line_length = []
1111
- for m, l, a in lines:
1112
- if np.isclose(m_prev, m):
1113
- l_total += l
1114
- else:
1115
- if l_total > 0.0:
1116
- line_length.append((l_total, m_prev, a_prev))
1117
- l_total = l
1118
- m_prev = m
1119
- a_prev = a
1120
-
1121
- if l_total > 0.0:
1122
- line_length.append((l_total, m_prev, a_prev))
1123
- line_length.sort(reverse=True)
1124
-
1125
- alpha = line_length[0][2]
1126
- if alpha < 0.0:
1127
- alpha += np.pi
1128
- alpha = alpha + np.pi/2
1129
- if alpha > np.pi:
1130
- alpha = alpha - np.pi
1131
- return alpha
1132
-
1133
- def get_mag_orientation(self):
1134
- if self.mag_rectangle:
1135
- return self.get_mag_orient_rectangle()
1095
+ length_0, angle_0 = angles[0]
1096
+ length_1, angle_1 = angles[1]
1097
+ length_2, angle_2 = angles[2]
1098
+ length_3, angle_3 = angles[3]
1136
1099
 
1137
- if self.close_to_endangle:
1138
- if self.close_to_startangle:
1139
- return middle_angle(self.min_angle, self.max_angle)
1140
- else:
1141
- return self.max_angle
1100
+ if not np.isclose(angle_0, angle_2, rtol=1e-03, atol=0.05):
1101
+ logger.debug("is_magnet_rectangle: angles %s and %s not equal",
1102
+ angle_0, angle_2)
1103
+ return False
1104
+
1105
+ if not np.isclose(angle_1, angle_3, rtol=1e-03, atol=0.05):
1106
+ logger.debug("is_magnet_rectangle: angles %s and %s not equal",
1107
+ angle_1, angle_3)
1108
+ return False
1109
+
1110
+ if angle_0 > angle_1:
1111
+ a0 = angle_0
1112
+ a1 = angle_1 + np.pi/2
1142
1113
  else:
1143
- return middle_angle(self.min_angle, self.max_angle)
1114
+ a0 = angle_1
1115
+ a1 = angle_0 + np.pi/2
1116
+ if not np.isclose(a0, a1, rtol=1e-03, atol=0.05):
1117
+ logger.debug("is_magnet_rectangle: not a rectange (%s neq %s)", a0, a1)
1118
+ return False
1119
+
1120
+ turn_left = False
1121
+ turn_right = False
1122
+ for n1, n2, e in self.list_of_elements():
1123
+ if is_Arc(e):
1124
+ if e.get_node_number(n1) == 1:
1125
+ turn_left = True
1126
+ else:
1127
+ turn_right = True
1128
+
1129
+ if turn_left and turn_right:
1130
+ logger.debug("is_magnet_rectangle: arcs with different directions")
1131
+ return False
1132
+
1133
+ self.phi = self.get_magnet_phi(angles)
1134
+ angles.sort()
1135
+ l, alpha = angles[0]
1136
+ self.mag_width = l
1137
+ logger.debug("Area %s is a rectangle with phi %s",
1138
+ self.identifier(), self.phi)
1139
+ return True
1144
1140
 
1145
1141
  def around_windings(self, areas, geom):
1146
1142
  for a in areas:
@@ -1164,6 +1160,10 @@ class Area(object):
1164
1160
  return True
1165
1161
  return False
1166
1162
 
1163
+ def is_close_to_border(self, angle, border_angle):
1164
+ return np.isclose(angle, border_angle,
1165
+ rtol=1e-03, atol=1e-03)
1166
+
1167
1167
  def mark_stator_subregions(self,
1168
1168
  is_inner,
1169
1169
  stator_size,
@@ -1175,7 +1175,7 @@ class Area(object):
1175
1175
  alpha = round(alpha, 6)
1176
1176
 
1177
1177
  if self.is_circle():
1178
- self.type = 0 # air
1178
+ self.type = TYPE_AIR # air
1179
1179
  return self.type
1180
1180
 
1181
1181
  ag_delta = (r_out - r_in) / 500.0
@@ -1216,24 +1216,24 @@ class Area(object):
1216
1216
 
1217
1217
  if self.has_iron_separator():
1218
1218
  logger.debug("***** iron (has iron separator)\n")
1219
- self.type = 1 # iron
1219
+ self.type = TYPE_IRON # iron
1220
1220
  return self.type
1221
1221
 
1222
1222
  if is_inner:
1223
1223
  # looking for shaft
1224
1224
  if close_to_opposition and not self.close_to_ag:
1225
1225
  if self.is_shaft_area(center):
1226
- self.type = 10 # shaft
1226
+ self.type = TYPE_SHAFT # shaft
1227
1227
  logger.debug("***** shaft (close to opposition)\n")
1228
1228
  return self.type
1229
1229
 
1230
1230
  if close_to_opposition:
1231
- self.type = 5 # iron yoke (Joch)
1231
+ self.type = TYPE_YOKE # iron yoke (Joch)
1232
1232
  logger.debug("***** iron yoke #1\n")
1233
1233
  return self.type
1234
1234
 
1235
1235
  if self.close_to_startangle and self.close_to_endangle:
1236
- self.type = 5 # iron yoke (Joch)
1236
+ self.type = TYPE_YOKE # iron yoke (Joch)
1237
1237
  logger.debug("***** iron yoke #2\n")
1238
1238
  return self.type
1239
1239
 
@@ -1250,21 +1250,21 @@ class Area(object):
1250
1250
 
1251
1251
  if self.alpha / air_alpha > 2:
1252
1252
  logger.debug("***** windings near airgap\n")
1253
- self.type = 2 # windings
1253
+ self.type = TYPE_WINDINGS # windings
1254
1254
  else:
1255
- self.type = 9 # air or iron near windings and near airgap?
1255
+ self.type = TYPE_AIR_OR_IRON # air or iron near windings and near airgap?
1256
1256
  logger.debug("***** air or iron ??\n")
1257
1257
  return self.type
1258
1258
 
1259
1259
  if self.close_to_startangle:
1260
1260
  if self.is_half_circle(center, self.min_angle):
1261
- self.type = 0 # air
1261
+ self.type = TYPE_AIR # air
1262
1262
  logger.debug("***** air (part of a circle)\n")
1263
1263
  return self.type
1264
1264
 
1265
1265
  if self.close_to_endangle:
1266
1266
  if self.is_half_circle(center, self.max_angle):
1267
- self.type = 0 # air
1267
+ self.type = TYPE_AIR # air
1268
1268
  logger.debug("***** air (part of a circle)\n")
1269
1269
  return self.type
1270
1270
 
@@ -1282,32 +1282,32 @@ class Area(object):
1282
1282
  if self.min_angle > 0.001:
1283
1283
  if self.max_angle < alpha - 0.001:
1284
1284
  if bad_winding_position():
1285
- self.type = 12 # windings or air
1285
+ self.type = TYPE_WINDINGS_OR_AIR # windings or air
1286
1286
  logger.debug("***** windings or air #1\n")
1287
1287
  else:
1288
- self.type = 2 # windings
1288
+ self.type = TYPE_WINDINGS # windings
1289
1289
  logger.debug("***** windings #1\n")
1290
1290
  return self.type
1291
1291
  if mirrored:
1292
1292
  if bad_winding_position():
1293
- self.type = 12 # windings or air
1293
+ self.type = TYPE_WINDINGS_OR_AIR # windings or air
1294
1294
  logger.debug("***** windings or air #2\n")
1295
1295
  else:
1296
- self.type = 2 # windings
1296
+ self.type = TYPE_WINDINGS # windings
1297
1297
  logger.debug("***** windings #2\n")
1298
1298
  return self.type
1299
1299
 
1300
- self.type = 0 # air
1300
+ self.type = TYPE_AIR # air
1301
1301
  logger.debug("***** air #3")
1302
1302
 
1303
1303
  if self.close_to_startangle or self.close_to_endangle:
1304
1304
  f = self.surface / stator_size
1305
1305
  if f < 0.02: # area_size less then 2 percent of stator size
1306
1306
  # Luftloch
1307
- self.type = 0 # air
1307
+ self.type = TYPE_AIR # air
1308
1308
  logger.debug("***** small area => air\n")
1309
1309
  else:
1310
- self.type = 9 # air or iron near windings and near airgap?
1310
+ self.type = TYPE_AIR_OR_IRON # air or iron near windings and near airgap?
1311
1311
  logger.debug("***** air or iron close to border\n")
1312
1312
  return self.type
1313
1313
 
@@ -1315,32 +1315,34 @@ class Area(object):
1315
1315
  return 0
1316
1316
 
1317
1317
  def mark_rotor_subregions(self, is_inner, mirrored, alpha,
1318
- center, r_in, r_out):
1318
+ center, r_in, r_out,
1319
+ startangle,
1320
+ endangle):
1319
1321
  logger.debug("mark_rotor_subregions")
1320
1322
 
1321
1323
  alpha = round(alpha, 6)
1322
1324
 
1323
1325
  if self.is_circle():
1324
- self.type = 0 # air
1326
+ self.type = TYPE_AIR # air
1325
1327
  logger.debug(">>> air is a circle")
1326
1328
  return self.type
1327
1329
 
1328
1330
  if is_inner:
1329
- self.close_to_ag = np.isclose(r_out, self.max_dist, atol=0.005)
1331
+ self.close_to_ag = np.isclose(r_out, self.max_dist, rtol=1e-9, atol=0.005)
1330
1332
  close_to_opposition = greater_equal(r_in * 1.05, self.min_dist)
1331
1333
  airgap_radius = r_out
1332
1334
  opposite_radius = r_in
1333
1335
  airgap_toleranz = -(self.max_dist - self.min_dist) / 50.0 # 2%
1334
1336
  else:
1335
- self.close_to_ag = np.isclose(r_in, self.min_dist, atol=0.005)
1337
+ self.close_to_ag = np.isclose(r_in, self.min_dist, rtol=1e-9, atol=0.005)
1336
1338
  close_to_opposition = greater_equal(self.max_dist * 1.05, r_out)
1337
1339
  airgap_radius = r_in
1338
1340
  opposite_radius = r_out
1339
1341
  airgap_toleranz = (self.max_dist - self.min_dist) / 50.0 # 2%
1340
1342
 
1341
- self.close_to_startangle = np.isclose(self.min_angle, 0.0,
1343
+ self.close_to_startangle = np.isclose(self.min_angle, startangle,
1342
1344
  1e-04, 1e-04)
1343
- self.close_to_endangle = np.isclose(self.max_angle, alpha,
1345
+ self.close_to_endangle = np.isclose(self.max_angle, endangle,
1344
1346
  1e-04, 1e-04)
1345
1347
 
1346
1348
  logger.debug("\n***** mark_rotor_subregions [{}] *****"
@@ -1359,28 +1361,29 @@ class Area(object):
1359
1361
 
1360
1362
  if self.has_iron_separator():
1361
1363
  logger.debug("***** iron (has iron separator)\n")
1362
- self.type = 1 # iron
1364
+ self.type = TYPE_IRON # iron
1363
1365
  return self.type
1364
1366
 
1365
1367
  if is_inner:
1366
1368
  # looking for shaft
1367
1369
  if close_to_opposition and not self.close_to_ag:
1370
+ logger.debug("-- check for shaft")
1368
1371
  if self.is_shaft_area(center):
1369
- self.type = 10 # shaft
1372
+ self.type = TYPE_SHAFT # shaft
1370
1373
  logger.debug("***** shaft (close to opposition)\n")
1371
1374
  return self.type
1372
1375
 
1373
1376
  if close_to_opposition:
1374
- self.type = 1 # iron
1377
+ self.type = TYPE_IRON # iron
1375
1378
  logger.debug("***** iron (close to opposition)\n")
1376
1379
  return self.type
1377
1380
 
1378
1381
  if self.close_to_startangle and self.close_to_endangle:
1379
- self.type = 1 # iron
1382
+ self.type = TYPE_IRON # iron
1380
1383
  logger.debug("***** iron (close to both sides)\n")
1381
1384
  return self.type
1382
1385
 
1383
- self.mag_rectangle = self.is_mag_rectangle()
1386
+ self.mag_rectangle = self.is_magnet_rectangle()
1384
1387
 
1385
1388
  if self.close_to_ag:
1386
1389
  mm = self.minmax_angle_dist_from_center(center,
@@ -1389,47 +1392,50 @@ class Area(object):
1389
1392
  air_alpha = round(alpha_angle(mm[0], mm[1]), 3)
1390
1393
  logger.debug(" - air_alpha : {}".format(air_alpha))
1391
1394
 
1395
+ if self.mag_rectangle:
1396
+ self.type = TYPE_MAGNET_RECT_NEAR_AIRGAP # magnet near airgap
1397
+ logger.debug("***** magnet (airgap, embedded, phi={})\n".
1398
+ format(self.phi))
1399
+ return self.type
1400
+
1392
1401
  if air_alpha / alpha < 0.2:
1393
- self.phi = self.get_mag_orientation()
1394
- self.type = 8 # air or magnet ?
1402
+ self.type = TYPE_MAGNET_OR_AIR # air or magnet ?
1395
1403
  logger.debug("***** air #1 (close to airgap)\n")
1396
1404
  return self.type
1397
1405
 
1398
1406
  if air_alpha / alpha > 0.6:
1399
- self.phi = self.get_mag_orientation()
1400
- self.type = 3 # magnet
1407
+ self.type = TYPE_MAGNET_AIRGAP # magnet (no rectangle)
1401
1408
  logger.debug("***** magnet (close to airgap)\n")
1402
1409
  else:
1403
- self.phi = self.get_mag_orientation()
1404
- self.type = 9 # iron or magnet ?
1410
+ self.type = TYPE_MAGNET_OR_IRON # iron or magnet ?
1405
1411
  logger.debug("***** iron or magnet(close to airgap)\n")
1406
1412
  return self.type
1407
1413
 
1408
1414
  if self.mag_rectangle:
1409
- self.phi = self.get_mag_orientation()
1410
- self.type = 4 # magnet embedded
1415
+ # phi is already calculated and set
1416
+ self.type = TYPE_MAGNET_RECT # magnet embedded
1411
1417
  logger.debug("***** magnet (embedded, phi={})\n".format(
1412
1418
  self.phi))
1413
1419
  return self.type
1414
1420
 
1415
1421
  if not (self.close_to_startangle or self.close_to_endangle):
1416
- self.type = 0 # air
1422
+ self.type = TYPE_AIR # air
1417
1423
  logger.debug("***** air (somewhere)\n")
1418
1424
  return self.type
1419
1425
 
1420
1426
  if self.close_to_startangle:
1421
1427
  if self.is_half_circle(center, self.min_angle):
1422
- self.type = 0 # air
1428
+ self.type = TYPE_AIR # air
1423
1429
  logger.debug("***** air (part of a circle)\n")
1424
1430
  return self.type
1425
1431
 
1426
1432
  if self.close_to_endangle:
1427
1433
  if self.is_half_circle(center, self.max_angle):
1428
- self.type = 0 # air
1434
+ self.type = TYPE_AIR # air
1429
1435
  logger.debug("***** air (part of a circle)\n")
1430
1436
  return self.type
1431
1437
 
1432
- self.type = 0 # air
1438
+ self.type = TYPE_AIR # air
1433
1439
  logger.debug("***** air (remains)\n")
1434
1440
  return self.type
1435
1441
 
@@ -1438,33 +1444,32 @@ class Area(object):
1438
1444
  logger.debug("mark_unknown_subregions")
1439
1445
 
1440
1446
  if self.is_circle():
1441
- self.type = 0 # air
1447
+ self.type = TYPE_AIR # air
1442
1448
  logger.debug(">>> air is a circle")
1443
1449
  return self.type
1444
1450
 
1445
1451
  self.close_to_startangle = np.isclose(self.min_angle, 0.0)
1446
1452
  self.close_to_endangle = np.isclose(self.max_angle, alpha)
1447
1453
 
1448
- if self.is_mag_rectangle():
1449
- self.type = 4 # magnet embedded
1454
+ if self.is_magnet_rectangle():
1455
+ self.type = TYPE_MAGNET_RECT # magnet embedded
1450
1456
  logger.debug(">>> magnet embedded")
1451
- self.phi = self.get_mag_orient_rectangle()
1452
1457
  return self.type
1453
1458
 
1454
1459
  close_to_max_radius = np.isclose(r_out, self.max_dist)
1455
1460
  close_to_min_radius = np.isclose(r_in, self.min_dist)
1456
1461
 
1457
1462
  if close_to_max_radius and close_to_min_radius:
1458
- self.type = 1 # iron
1463
+ self.type = TYPE_IRON # iron
1459
1464
  logger.debug(">>> iron close to min- and max-radius")
1460
1465
  return self.type
1461
1466
 
1462
1467
  if self.close_to_startangle and self.close_to_endangle:
1463
- self.type = 1 # iron
1468
+ self.type = TYPE_IRON # iron
1464
1469
  logger.debug(">>> iron close to start- and end-angle")
1465
1470
  return self.type
1466
1471
 
1467
- self.type = 0 # air
1472
+ self.type = TYPE_AIR # air
1468
1473
  logger.debug(">>> air remains")
1469
1474
  return self.type
1470
1475
 
@@ -1551,74 +1556,6 @@ class Area(object):
1551
1556
  for i in a.nested_areas_inside():
1552
1557
  yield i
1553
1558
 
1554
- def crunch_area(self, geom):
1555
- n1_prev = None
1556
- e_prev = None
1557
- logger.debug("crunch area %s", self.identifier())
1558
-
1559
- if self.is_circle():
1560
- return 0
1561
-
1562
- c = 0
1563
- for n1, n2, e in self.list_of_elements():
1564
- if e_prev is not None:
1565
- if len([nbr for nbr in geom.g.neighbors(n1)]) == 2:
1566
- e_new = e_prev.concatenate(n1_prev, n2, e)
1567
- if e_new is not None:
1568
- e_prev_dict = geom.g.get_edge_data(n1_prev, n1)
1569
- e_dict = geom.g.get_edge_data(n1, n2)
1570
-
1571
- logger.debug("--> remove from %s to %s [%s, %s, %s]",
1572
- n1_prev,
1573
- n1,
1574
- e_prev_dict[0],
1575
- e_prev_dict[1],
1576
- e_prev_dict[2])
1577
- logger.debug(" remove %s", e_prev)
1578
- geom.remove_edge(e_prev)
1579
-
1580
- logger.debug("--> remove from %s to %s [%s, %s, %s]",
1581
- n1,
1582
- n2,
1583
- e_dict[0],
1584
- e_dict[1],
1585
- e_dict[2])
1586
- logger.debug(" remove %s", e)
1587
- if e.get_node_number(n1) == 1:
1588
- flag1 = e_dict[1]
1589
- flag2 = e_dict[2]
1590
- else:
1591
- flag1 = e_dict[2]
1592
- flag2 = e_dict[1]
1593
- geom.remove_edge(e)
1594
-
1595
- logger.debug("--> add from %s to %s",
1596
- n1_prev,
1597
- n2)
1598
- logger.debug(" add %s", e_new)
1599
- geom.add_edge(n1_prev, n2, e_new)
1600
-
1601
- e_new_dict = geom.g.get_edge_data(n1_prev, n2)
1602
- e_new_dict[0] = True
1603
- if e_new.get_node_number(n1_prev) == 1:
1604
- e_new_dict[1] = flag1
1605
- e_new_dict[2] = flag2
1606
- else:
1607
- e_new_dict[1] = flag2
1608
- e_new_dict[2] = flag1
1609
-
1610
- logger.debug(" new dict: [%s, %s, %s]",
1611
- e_new_dict[0],
1612
- e_new_dict[1],
1613
- e_new_dict[2])
1614
- e_prev = e_new
1615
- c += 1
1616
- continue
1617
-
1618
- n1_prev = n1
1619
- e_prev = e
1620
- return c
1621
-
1622
1559
  def __str__(self):
1623
1560
  return "Area {}\n".format(self.id) + \
1624
1561
  "distance...............: from {} to {}\n".\