femagtools 1.6.5__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 +24 -4
- 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/shape.py +1 -1
- femagtools/dxfsl/svgparser.py +90 -0
- femagtools/dxfsl/symmetry.py +183 -74
- femagtools/isa7.py +6 -5
- femagtools/machine/effloss.py +1 -1
- femagtools/machine/im.py +2 -1
- femagtools/machine/pm.py +71 -12
- femagtools/machine/sm.py +4 -2
- femagtools/plot/nc.py +3 -3
- femagtools/svgfsl/converter.py +74 -0
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/METADATA +5 -1
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/RECORD +26 -21
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/entry_points.txt +1 -0
- tests/test_dxfsl.py +12 -0
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/LICENSE +0 -0
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/WHEEL +0 -0
- {femagtools-1.6.5.dist-info → femagtools-1.6.6.dist-info}/top_level.txt +0 -0
femagtools/__init__.py
CHANGED
femagtools/dxfsl/area.py
CHANGED
@@ -45,6 +45,7 @@ class Area(object):
|
|
45
45
|
self.mag_rectangle = False
|
46
46
|
self.min_dist = 99999.0
|
47
47
|
self.max_dist = 0.0
|
48
|
+
self.minmax_xy = [0,0,0,0]
|
48
49
|
self.height = 0.0
|
49
50
|
self.alpha = 0.0
|
50
51
|
self.count = 1
|
@@ -269,6 +270,7 @@ class Area(object):
|
|
269
270
|
if not self.area:
|
270
271
|
return
|
271
272
|
|
273
|
+
self.minmax_xy = self.minmax()
|
272
274
|
s = self.area[0]
|
273
275
|
mm_angle = s.minmax_angle_from_center(center)
|
274
276
|
self.min_angle = mm_angle[0]
|
@@ -286,6 +288,12 @@ class Area(object):
|
|
286
288
|
|
287
289
|
self.alpha = round(alpha_angle(self.min_angle, self.max_angle), 3)
|
288
290
|
|
291
|
+
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]:
|
294
|
+
return True
|
295
|
+
return False
|
296
|
+
|
289
297
|
def minmax_angle_dist_from_center(self, center, dist):
|
290
298
|
circ = Circle(Element(center=center, radius=dist))
|
291
299
|
s = self.area[0]
|
@@ -429,10 +437,14 @@ class Area(object):
|
|
429
437
|
(the_axis_p[0], the_axis_p[1]),
|
430
438
|
(the_area_p[0], the_area_p[1]))
|
431
439
|
|
432
|
-
def get_alpha(self):
|
440
|
+
def get_alpha(self, center):
|
441
|
+
if self.center_is_inside(center):
|
442
|
+
return np.pi*2.0
|
433
443
|
return alpha_angle(self.min_angle, self.max_angle)
|
434
444
|
|
435
|
-
def get_mid_angle(self):
|
445
|
+
def get_mid_angle(self, center):
|
446
|
+
if self.center_is_inside(center):
|
447
|
+
return np.pi
|
436
448
|
return middle_angle(self.min_angle, self.max_angle)
|
437
449
|
|
438
450
|
def is_equal(self, a, sym_tolerance):
|
@@ -636,7 +648,7 @@ class Area(object):
|
|
636
648
|
return False
|
637
649
|
|
638
650
|
def get_best_point_inside(self, geom):
|
639
|
-
mm = self.
|
651
|
+
mm = self.minmax_xy
|
640
652
|
px1 = mm[0]-5
|
641
653
|
px2 = mm[1]+5
|
642
654
|
|
@@ -733,7 +745,7 @@ class Area(object):
|
|
733
745
|
|
734
746
|
def get_point_inside(self, geom):
|
735
747
|
"""return point inside area"""
|
736
|
-
mm = self.
|
748
|
+
mm = self.minmax_xy
|
737
749
|
y = (mm[2]+mm[3])/2
|
738
750
|
p1 = (mm[0]-5, y)
|
739
751
|
p2 = (mm[1]+5, y)
|
@@ -1466,6 +1478,14 @@ class Area(object):
|
|
1466
1478
|
self.close_to_ag_endcorner = True
|
1467
1479
|
|
1468
1480
|
def area_size(self):
|
1481
|
+
if len(self.area) == 0:
|
1482
|
+
return 0.0
|
1483
|
+
if self.number_of_elements() < 2:
|
1484
|
+
e = self.area[0]
|
1485
|
+
if not is_Circle(e):
|
1486
|
+
return 0.0
|
1487
|
+
return np.pi * e.radius**2
|
1488
|
+
|
1469
1489
|
nodes = [n for n in self.list_of_nodes()]
|
1470
1490
|
return area_size(nodes)
|
1471
1491
|
|
femagtools/dxfsl/areabuilder.py
CHANGED
@@ -341,9 +341,11 @@ class AreaBuilder(object):
|
|
341
341
|
def __init__(self,
|
342
342
|
geom=None,
|
343
343
|
rtol=1e-04,
|
344
|
-
atol=1e-04
|
344
|
+
atol=1e-04,
|
345
|
+
ndec=6):
|
345
346
|
self.rtol = rtol
|
346
347
|
self.atol = atol
|
348
|
+
self.ndec = ndec
|
347
349
|
self.geom = geom
|
348
350
|
self.area_list = []
|
349
351
|
self.journal = getJournal()
|
@@ -358,7 +360,13 @@ class AreaBuilder(object):
|
|
358
360
|
|
359
361
|
def set_edge_attributes(self):
|
360
362
|
self.geom.set_edge_attributes()
|
361
|
-
|
363
|
+
|
364
|
+
def append_new_area(self, area_list, elements):
|
365
|
+
a = Area(elements, self.geom.center, 0.0)
|
366
|
+
a.type = 0 # air
|
367
|
+
area_list.append(a)
|
368
|
+
return a
|
369
|
+
|
362
370
|
def create_list_of_areas(self, main=False):
|
363
371
|
logger.debug("Begin of create_list_of_areas")
|
364
372
|
assert(len(self.area_list) == 0)
|
@@ -382,10 +390,8 @@ class AreaBuilder(object):
|
|
382
390
|
for next_n in nbrs:
|
383
391
|
result = self.get_new_area(n, next_n)
|
384
392
|
if result['ok']:
|
385
|
-
|
386
|
-
a = Area(area, self.geom.center, 0.0)
|
393
|
+
a = self.append_new_area(self.area_list, result['area'])
|
387
394
|
logger.debug("Area %s found", a.identifier())
|
388
|
-
append(self.area_list, a)
|
389
395
|
|
390
396
|
t = timer.stop("{} areas created in %0.4f seconds".format(len(self.area_list)))
|
391
397
|
if main:
|
@@ -564,3 +570,144 @@ class AreaBuilder(object):
|
|
564
570
|
nbr1.log_edge(">>>> LEFT")
|
565
571
|
logger.debug("end of next_edge_lefthand_side")
|
566
572
|
return nbr1
|
573
|
+
|
574
|
+
def create_inner_corner_auxiliary_areas(self):
|
575
|
+
logger.debug("begin of create_inner_corner_auxiliary_areas")
|
576
|
+
if not self.geom.is_inner:
|
577
|
+
logger.debug("end of create_inner_corner_auxiliary_areas: not inner")
|
578
|
+
return
|
579
|
+
|
580
|
+
self.set_edge_attributes()
|
581
|
+
|
582
|
+
start_cp, start_exists = self.geom.get_start_airgap_corner()
|
583
|
+
end_cp, end_exists = self.geom.get_end_airgap_corner()
|
584
|
+
if start_exists and end_exists:
|
585
|
+
logger.debug("end of create_inner_corner_auxiliary_areas: no aktion")
|
586
|
+
return
|
587
|
+
|
588
|
+
airgap_line, airgap_el = self.get_inner_airgap_line()
|
589
|
+
if not airgap_el:
|
590
|
+
logger.debug("end of create_inner_corner_auxiliary_areas: no airgapline found")
|
591
|
+
return
|
592
|
+
|
593
|
+
logger.debug("airgapline found !!")
|
594
|
+
airgap_nodes = [n for n in airgap_line[1:]]
|
595
|
+
del airgap_nodes[-1]
|
596
|
+
|
597
|
+
if not start_exists:
|
598
|
+
cp = self.geom.start_corners[-1]
|
599
|
+
logger.debug("Start Corner: %s -- %s", cp, start_cp)
|
600
|
+
start_line = Line(Element(start=cp, end=start_cp),
|
601
|
+
color='red',
|
602
|
+
linestyle='dotted')
|
603
|
+
|
604
|
+
start_cp = start_line.node2(self.ndec)
|
605
|
+
for n in airgap_nodes:
|
606
|
+
ag_line = Line(Element(start=start_cp, end=n))
|
607
|
+
points = self.geom.get_intersection_points(airgap_el, ag_line, n)
|
608
|
+
if not points: # no intersection
|
609
|
+
d = distance(self.geom.center, n)
|
610
|
+
if np.isclose(d, self.geom.max_radius):
|
611
|
+
self.geom.add_arc(start_cp,
|
612
|
+
n,
|
613
|
+
self.geom.center,
|
614
|
+
self.geom.max_radius,
|
615
|
+
color='red',
|
616
|
+
linestyle='dotted')
|
617
|
+
else:
|
618
|
+
self.geom.add_line(start_cp,
|
619
|
+
n,
|
620
|
+
color='red',
|
621
|
+
linestyle='dotted')
|
622
|
+
self.geom.add_edge(cp, start_cp, start_line)
|
623
|
+
result = self.get_new_area(start_cp, n)
|
624
|
+
if result['ok']:
|
625
|
+
self.append_new_area(self.geom.area_list,
|
626
|
+
result['area'])
|
627
|
+
self.geom.set_start_corners(self.geom.center, 0.0)
|
628
|
+
break
|
629
|
+
|
630
|
+
if not end_exists:
|
631
|
+
cp = self.geom.end_corners[-1]
|
632
|
+
logger.debug("End Corner: %s -- %s", cp, end_cp)
|
633
|
+
end_line = Line(Element(start=cp, end=end_cp),
|
634
|
+
color='red',
|
635
|
+
linestyle='dotted')
|
636
|
+
end_cp = end_line.node2(self.ndec)
|
637
|
+
airgap_nodes.reverse()
|
638
|
+
for n in airgap_nodes:
|
639
|
+
ag_line = Line(Element(start=end_cp, end=n))
|
640
|
+
points = self.geom.get_intersection_points(airgap_el, ag_line, n)
|
641
|
+
if not points: # no intersection
|
642
|
+
d = distance(self.geom.center, n)
|
643
|
+
if np.isclose(d, self.geom.max_radius):
|
644
|
+
self.geom.add_arc(n, end_cp,
|
645
|
+
self.geom.center,
|
646
|
+
self.geom.max_radius,
|
647
|
+
color='red',
|
648
|
+
linestyle='dotted')
|
649
|
+
else:
|
650
|
+
self.geom.add_line(end_cp, n,
|
651
|
+
color='red',
|
652
|
+
linestyle='dotted')
|
653
|
+
self.geom.add_edge(cp, end_cp, end_line)
|
654
|
+
result = self.get_new_area(n, end_cp)
|
655
|
+
if result['ok']:
|
656
|
+
self.append_new_area(self.geom.area_list,
|
657
|
+
result['area'])
|
658
|
+
self.geom.set_end_corners(self.geom.center, self.geom.alfa)
|
659
|
+
break
|
660
|
+
|
661
|
+
logger.debug("end of create_inner_corner_auxiliary_areas")
|
662
|
+
|
663
|
+
def get_inner_airgap_line(self):
|
664
|
+
logger.debug("begin of get_inner_airgap_line")
|
665
|
+
assert(self.geom.is_inner)
|
666
|
+
assert(self.geom.area_list)
|
667
|
+
|
668
|
+
area = [a for a in self.geom.area_list if a.close_to_ag_endcorner]
|
669
|
+
if len(area) != 1:
|
670
|
+
logger.debug("end of get_inner_airgap_line: %s areas found", len(area))
|
671
|
+
return [], []
|
672
|
+
|
673
|
+
end_corner = self.geom.end_corners[-1]
|
674
|
+
logger.debug("END CORNER %s", end_corner)
|
675
|
+
|
676
|
+
nodes = [n for n in area[0].list_of_nodes()]
|
677
|
+
if not nodes:
|
678
|
+
logger.debug("end of get_inner_airgap_line: no nodes found")
|
679
|
+
return [], []
|
680
|
+
|
681
|
+
n1 = nodes[0]
|
682
|
+
if points_are_close(end_corner, n1):
|
683
|
+
n2 = nodes[-1]
|
684
|
+
else:
|
685
|
+
n2 = n1
|
686
|
+
for n1 in nodes[1:]:
|
687
|
+
if points_are_close(end_corner, n1):
|
688
|
+
break
|
689
|
+
n2 = n1
|
690
|
+
|
691
|
+
if not points_are_close(end_corner, n1):
|
692
|
+
logger.debug("end of get_inner_airgap_line: not close to endcorner")
|
693
|
+
return [], []
|
694
|
+
|
695
|
+
start_corner = self.geom.start_corners[-1]
|
696
|
+
logger.debug("START CORNER %s", end_corner)
|
697
|
+
|
698
|
+
logger.debug("EDGE FOUND: %s - %s", n1, n2)
|
699
|
+
nodes = [n1, n2]
|
700
|
+
info = self.get_edge_info(n1, n2)
|
701
|
+
elements = [info.element]
|
702
|
+
|
703
|
+
while not points_are_close(start_corner, n2):
|
704
|
+
info.set_start_angle()
|
705
|
+
info = self.next_edge_lefthand_side(info)
|
706
|
+
if not info: # bad
|
707
|
+
return []
|
708
|
+
n2 = info.n2
|
709
|
+
nodes.append(n2)
|
710
|
+
elements.append(info.element)
|
711
|
+
|
712
|
+
logger.debug("end of get_inner_airgap_line #%s", len(nodes))
|
713
|
+
return nodes, elements
|
femagtools/dxfsl/concat.py
CHANGED
@@ -204,9 +204,9 @@ class Concatenation(object):
|
|
204
204
|
elmts.sort()
|
205
205
|
|
206
206
|
logger.debug("Concatenate Line Elements")
|
207
|
-
for m, a, p, e in elmts:
|
208
|
-
|
209
|
-
|
207
|
+
#for m, a, p, e in elmts:
|
208
|
+
# logger.debug("Line from %s to %s [m=%s, a=%s]",
|
209
|
+
# e.p1, e.p2, m, a)
|
210
210
|
logger.debug("*************************")
|
211
211
|
|
212
212
|
lines_available = len(elmts)
|
@@ -281,9 +281,9 @@ class Concatenation(object):
|
|
281
281
|
elmts.sort()
|
282
282
|
|
283
283
|
logger.debug("Concatenate Arc Elements")
|
284
|
-
for c, r, a, e in elmts:
|
285
|
-
|
286
|
-
|
284
|
+
#for c, r, a, e in elmts:
|
285
|
+
# logger.debug("%s from %s to %s [c=%s, r=%s, a=%s]",
|
286
|
+
# e.classname(), e.p1, e.p2, c, r, a)
|
287
287
|
logger.debug("*************************")
|
288
288
|
|
289
289
|
arcs_available = len(elmts)
|
@@ -354,4 +354,4 @@ class Concatenation(object):
|
|
354
354
|
self.journal.put('time_concatenation', t)
|
355
355
|
|
356
356
|
logger.debug("End of concatenate_matching_elements")
|
357
|
-
return count
|
357
|
+
return count, new_list
|
femagtools/dxfsl/converter.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
"""read a dxf file and create a plot or fsl file
|
2
2
|
|
3
3
|
"""
|
4
|
-
import
|
5
|
-
from femagtools.dxfsl.geom import Geometry
|
4
|
+
from pathlib import Path
|
5
|
+
from femagtools.dxfsl.geom import Geometry
|
6
6
|
from femagtools.dxfsl.shape import Shape
|
7
7
|
from femagtools.dxfsl.fslrenderer import FslRenderer, agndst
|
8
8
|
from femagtools.dxfsl.plotrenderer import PlotRenderer
|
9
|
+
from femagtools.dxfsl.functions import Timer
|
9
10
|
import logging
|
10
11
|
import logging.config
|
11
12
|
import numpy as np
|
@@ -124,8 +125,9 @@ def convert(dxfile,
|
|
124
125
|
layers = ()
|
125
126
|
conv = {}
|
126
127
|
|
127
|
-
basename =
|
128
|
-
logger.info("start processing %s", basename)
|
128
|
+
basename = Path(dxfile).stem
|
129
|
+
logger.info("***** start processing %s *****", basename)
|
130
|
+
timer = Timer(start_it=True)
|
129
131
|
|
130
132
|
if part:
|
131
133
|
if part[0] not in ('rotor', 'stator'):
|
@@ -149,18 +151,28 @@ def convert(dxfile,
|
|
149
151
|
split_cpy = split
|
150
152
|
|
151
153
|
try:
|
152
|
-
if dxfile.
|
154
|
+
if Path(dxfile).suffix == '.fem':
|
155
|
+
from .femparser import femshapes
|
153
156
|
basegeom = Geometry(femshapes(dxfile),
|
154
157
|
rtol=rtol,
|
155
158
|
atol=atol,
|
156
159
|
split=split_ini)
|
157
|
-
|
160
|
+
elif Path(dxfile).suffix == '.dxf':
|
161
|
+
from .dxfparser import dxfshapes
|
158
162
|
basegeom = Geometry(dxfshapes(dxfile,
|
159
163
|
mindist=mindist,
|
160
164
|
layers=layers),
|
161
165
|
rtol=rtol,
|
162
166
|
atol=atol,
|
163
167
|
split=split_ini)
|
168
|
+
elif Path(dxfile).suffix == '.svg':
|
169
|
+
from .svgparser import svgshapes
|
170
|
+
basegeom = Geometry(svgshapes(dxfile),
|
171
|
+
rtol=rtol,
|
172
|
+
atol=atol,
|
173
|
+
split=split_ini)
|
174
|
+
|
175
|
+
|
164
176
|
except FileNotFoundError as ex:
|
165
177
|
logger.error(ex)
|
166
178
|
return dict()
|
@@ -187,7 +199,7 @@ def convert(dxfile,
|
|
187
199
|
machine_base = basegeom.get_machine()
|
188
200
|
if show_plots:
|
189
201
|
p.render_elements(basegeom, Shape,
|
190
|
-
title=
|
202
|
+
title=Path(dxfile).name,
|
191
203
|
with_hull=False,
|
192
204
|
rows=3, cols=2, num=1, show=debug_mode)
|
193
205
|
|
@@ -490,6 +502,7 @@ def convert(dxfile,
|
|
490
502
|
conv.update(params)
|
491
503
|
|
492
504
|
conv['name'] = basename
|
505
|
+
timer.stop("-- all done in %0.4f seconds --")
|
493
506
|
return conv
|
494
507
|
|
495
508
|
|