femagtools 1.6.8__py3-none-any.whl → 1.7.0__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 +2 -2
- femagtools/bch.py +1 -1
- femagtools/dxfsl/area.py +334 -332
- femagtools/dxfsl/areabuilder.py +131 -10
- femagtools/dxfsl/conv.py +27 -9
- femagtools/dxfsl/converter.py +390 -125
- femagtools/dxfsl/corner.py +3 -0
- femagtools/dxfsl/femparser.py +1 -1
- femagtools/dxfsl/fslrenderer.py +290 -246
- femagtools/dxfsl/functions.py +4 -2
- femagtools/dxfsl/geom.py +1120 -886
- femagtools/dxfsl/journal.py +53 -22
- femagtools/dxfsl/machine.py +250 -74
- femagtools/dxfsl/plotrenderer.py +34 -3
- femagtools/dxfsl/shape.py +380 -103
- femagtools/dxfsl/symmetry.py +679 -110
- femagtools/femag.py +27 -2
- femagtools/forcedens.py +65 -40
- femagtools/fsl.py +71 -28
- femagtools/losscoeffs.py +46 -0
- femagtools/machine/effloss.py +8 -1
- femagtools/machine/im.py +3 -1
- femagtools/machine/pm.py +11 -7
- femagtools/machine/sizing.py +14 -11
- femagtools/machine/sm.py +114 -33
- femagtools/machine/utils.py +38 -34
- femagtools/model.py +12 -2
- femagtools/moo/population.py +1 -1
- femagtools/parstudy.py +17 -1
- femagtools/plot/__init__.py +1 -1
- femagtools/plot/char.py +24 -7
- femagtools/plot/forcedens.py +56 -29
- femagtools/plot/mcv.py +4 -1
- femagtools/plot/phasor.py +6 -1
- femagtools/poc.py +17 -10
- femagtools/templates/cogg_calc.mako +7 -1
- femagtools/templates/displ_stator_rotor.mako +33 -0
- femagtools/templates/fieldcalc.mako +10 -16
- femagtools/templates/pm_sym_f_cur.mako +1 -1
- femagtools/tks.py +3 -9
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/LICENSE +1 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/METADATA +7 -4
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/RECORD +50 -49
- tests/engines/__init__.py +0 -20
- tests/geom/__init__.py +0 -20
- tests/moo/__init__.py +0 -20
- tests/test_model.py +8 -1
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/WHEEL +0 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/entry_points.txt +0 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.0.dist-info}/top_level.txt +0 -0
femagtools/dxfsl/geom.py
CHANGED
@@ -13,19 +13,25 @@ from __future__ import print_function
|
|
13
13
|
import numpy as np
|
14
14
|
import networkx as nx
|
15
15
|
import logging
|
16
|
+
import inspect
|
16
17
|
import sys
|
17
|
-
from
|
18
|
-
from .
|
18
|
+
from pathlib import Path
|
19
|
+
from femagtools.dxfsl.corner import Corner
|
20
|
+
from femagtools.dxfsl.area import Area
|
21
|
+
import femagtools.dxfsl.area as AREA
|
19
22
|
from .shape import Element, Shape, Circle, Arc, Line, Point
|
20
23
|
from .shape import is_Circle, is_Arc, is_Line
|
21
24
|
from .machine import Machine
|
25
|
+
from femagtools.dxfsl.concat import Concatenation
|
22
26
|
from femagtools.dxfsl.areabuilder import AreaBuilder
|
27
|
+
from femagtools.dxfsl.functions import Timer
|
28
|
+
from femagtools.dxfsl.journal import Journal, getJournal
|
23
29
|
from .functions import less_equal, less, greater, greater_equal
|
24
30
|
from .functions import distance, alpha_line, alpha_points, alpha_angle
|
25
31
|
from .functions import point, points_are_close, is_point_inside_region
|
26
32
|
from .functions import line_m, line_n, lines_intersect_point
|
27
33
|
from .functions import middle_point_of_line, middle_point_of_arc
|
28
|
-
from .functions import middle_angle
|
34
|
+
from .functions import middle_angle, positive_angle
|
29
35
|
from .functions import normalise_angle, is_same_angle
|
30
36
|
from .functions import part_of_circle, gcd
|
31
37
|
from .functions import point_on_arc, nodes_are_equal
|
@@ -40,6 +46,11 @@ nxversion = int(nx.__version__.split('.')[0])
|
|
40
46
|
geom_mindist = 0.0
|
41
47
|
|
42
48
|
|
49
|
+
def lineno():
|
50
|
+
"""Returns the current line number in our program."""
|
51
|
+
return inspect.currentframe().f_back.f_lineno
|
52
|
+
|
53
|
+
|
43
54
|
def plot_area(area):
|
44
55
|
"""plot area for debug purposes"""
|
45
56
|
import matplotlib.pylab as pl
|
@@ -73,6 +84,11 @@ def plot_area(area):
|
|
73
84
|
|
74
85
|
ndec = 6 # number of decimals to round to
|
75
86
|
|
87
|
+
def create_geometry(new_elements, split=False):
|
88
|
+
return Geometry(new_elements,
|
89
|
+
center=(0.0, 0.0),
|
90
|
+
split=split)
|
91
|
+
|
76
92
|
|
77
93
|
def intersect_and_split(inp_elements, rtol, atol):
|
78
94
|
logger.info("Load input elements ... ")
|
@@ -117,71 +133,6 @@ def add_or_split(el, x, out_elements, rtol, atol):
|
|
117
133
|
return []
|
118
134
|
|
119
135
|
|
120
|
-
def add_element(geom, e, rtol, atol):
|
121
|
-
n = geom.find_nodes(e.start(), e.end())
|
122
|
-
try:
|
123
|
-
add_or_join(geom, n[0], n[1], e, rtol, atol)
|
124
|
-
except Exception as ex:
|
125
|
-
logger.warn("EXCEPTION in add_element: %s", ex)
|
126
|
-
|
127
|
-
|
128
|
-
def add_or_join(geom, n1, n2, entity, rtol, atol):
|
129
|
-
""" adds a new entity to graph or joins entity with existing
|
130
|
-
geom: Geometry
|
131
|
-
n1, n2: nodes
|
132
|
-
entity
|
133
|
-
"""
|
134
|
-
if n1 == n2:
|
135
|
-
logger.debug(
|
136
|
-
"Tiny element with same node on both sides ignored: %s", n1)
|
137
|
-
logger.debug(
|
138
|
-
" -- element: %s", entity)
|
139
|
-
return
|
140
|
-
|
141
|
-
e = geom.get_edge_element(n1, n2)
|
142
|
-
if not e: # no duplicates
|
143
|
-
geom.add_edge(n1, n2, entity)
|
144
|
-
return
|
145
|
-
|
146
|
-
logger.debug("Duplicate connection: %s <--> %s", n1, n2)
|
147
|
-
if is_Line(e):
|
148
|
-
if is_Line(entity):
|
149
|
-
logger.debug("add_or_join(): Duplicate Lines ignored")
|
150
|
-
return # its ok
|
151
|
-
|
152
|
-
if is_Arc(e):
|
153
|
-
if is_Arc(entity):
|
154
|
-
if points_are_close(e.center, entity.center, rtol=rtol, atol=atol):
|
155
|
-
if points_are_close(e.p1, entity.p1):
|
156
|
-
logger.debug("add_or_join(): Duplicate Arcs ignored")
|
157
|
-
return # its ok
|
158
|
-
|
159
|
-
if is_Circle(entity):
|
160
|
-
if is_Circle(e):
|
161
|
-
logger.debug("add_or_join(): Duplicate Circle ignored")
|
162
|
-
return # its ok
|
163
|
-
|
164
|
-
if is_Circle(entity) or is_Circle(e):
|
165
|
-
e1, e2 = entity.cut_into_halves()
|
166
|
-
logger.debug("===== add_or_join(): Element near circle is cut into halves =====")
|
167
|
-
add_element(geom, e1, rtol, atol)
|
168
|
-
add_element(geom, e2, rtol, atol)
|
169
|
-
return # halves installed
|
170
|
-
|
171
|
-
m1 = e.center_of_connection()
|
172
|
-
m2 = entity.center_of_connection()
|
173
|
-
logger.debug("midpoints: %s -- %s", m1, m2)
|
174
|
-
if points_are_close(m1, m2, rtol, 1e-2):
|
175
|
-
logger.debug("Elements are close together")
|
176
|
-
return # ok
|
177
|
-
|
178
|
-
e1, e2 = entity.cut_into_halves()
|
179
|
-
logger.debug("===== add_or_join(): cut into halves =====")
|
180
|
-
add_element(geom, e1, rtol, atol)
|
181
|
-
add_element(geom, e2, rtol, atol)
|
182
|
-
return # halves installed
|
183
|
-
|
184
|
-
|
185
136
|
def get_nodes_of_paths(g, c):
|
186
137
|
nodes = set()
|
187
138
|
i = 1
|
@@ -290,11 +241,16 @@ class Geometry(object):
|
|
290
241
|
def __init__(self,
|
291
242
|
elements=[],
|
292
243
|
center=[],
|
293
|
-
rtol=1e-
|
244
|
+
rtol=1e-04,
|
294
245
|
atol=1e-03,
|
295
246
|
is_inner=False,
|
296
247
|
is_outer=False,
|
297
248
|
split=False,
|
249
|
+
concatenate=False,
|
250
|
+
connect=False,
|
251
|
+
delete=False,
|
252
|
+
adjust=False,
|
253
|
+
main=False,
|
298
254
|
debug=False):
|
299
255
|
self._name = ''
|
300
256
|
self.kind = ''
|
@@ -307,6 +263,7 @@ class Geometry(object):
|
|
307
263
|
self.sym_slice_angle = 0.0
|
308
264
|
self.alfa = 0.0
|
309
265
|
self.center = []
|
266
|
+
self.with_center_node = False
|
310
267
|
self.min_radius = 0.0
|
311
268
|
self.max_radius = 0.0
|
312
269
|
self.is_inner = is_inner
|
@@ -315,26 +272,61 @@ class Geometry(object):
|
|
315
272
|
self.sym_area = None
|
316
273
|
self.airgaps = []
|
317
274
|
self.area_list = []
|
275
|
+
self.areagroup_list = []
|
318
276
|
self.g = nx.Graph()
|
319
277
|
self.rtol = rtol
|
320
278
|
self.atol = atol
|
321
279
|
self.debug = debug
|
322
280
|
self.num_edges = 0
|
323
281
|
self.wdg_is_mirrored = False
|
282
|
+
self.has_windings = False
|
283
|
+
self.has_magnets = False
|
284
|
+
self.journal = getJournal()
|
285
|
+
self.area_errors = 0
|
324
286
|
i = 0
|
325
287
|
|
288
|
+
logger.debug("Geometry(split=%s, concat=%s, connect=%s, delete=%s, adjust=%s, main=%s,",
|
289
|
+
split, concatenate, connect, delete, adjust, main)
|
290
|
+
logger.debug(" rtol=%s, atol=%s)",
|
291
|
+
rtol, atol)
|
292
|
+
|
293
|
+
timer = Timer(start_it=True)
|
294
|
+
self.c_concat = 0
|
295
|
+
self.c_connect = 0
|
296
|
+
|
326
297
|
def get_elements(elements, split):
|
327
298
|
if split:
|
328
299
|
return intersect_and_split(elements, self.rtol, self.atol)
|
329
|
-
|
330
|
-
|
300
|
+
|
301
|
+
src_elements = [e for e in elements]
|
302
|
+
if main:
|
303
|
+
self.journal.put_elements(len(src_elements))
|
304
|
+
|
305
|
+
if not concatenate:
|
306
|
+
return src_elements
|
307
|
+
|
308
|
+
concat = Concatenation(rtol=self.rtol, atol=self.atol)
|
309
|
+
c, new_elements = concat.concatenate_matching_elements(src_elements,
|
310
|
+
main=main)
|
311
|
+
self.c_concat = c
|
312
|
+
return new_elements
|
313
|
+
|
314
|
+
nbr_nodes = []
|
315
|
+
if concatenate:
|
316
|
+
elements = [e for e in elements]
|
317
|
+
geom = Geometry(elements, center=(0.0, 0.0))
|
318
|
+
logger.debug("REAL GEOMETRY START ")
|
319
|
+
elements = geom.copy_all_elements(alpha=0.0)
|
320
|
+
nbr_nodes = geom.get_nodes(num_of_nbrs=[2, 4])
|
331
321
|
|
332
322
|
for e in get_elements(elements, split):
|
333
323
|
if e:
|
334
324
|
e.id = i
|
335
325
|
n = self.find_nodes(e.start(), e.end())
|
336
326
|
try:
|
337
|
-
|
327
|
+
self.add_or_join_edge(n[0], n[1], e,
|
328
|
+
rtol=self.rtol,
|
329
|
+
atol=self.atol)
|
338
330
|
except Exception as ex:
|
339
331
|
logger.warn("EXCEPTION %s", ex)
|
340
332
|
if e: # must be a circle
|
@@ -346,6 +338,29 @@ class Geometry(object):
|
|
346
338
|
if center:
|
347
339
|
self.set_center(center)
|
348
340
|
|
341
|
+
if connect:
|
342
|
+
self.c_connect = self.connect_all_appendices(rtol=1e-04,
|
343
|
+
atol=1e-03,
|
344
|
+
main=True)
|
345
|
+
if delete:
|
346
|
+
self.delete_all_appendices()
|
347
|
+
|
348
|
+
if concatenate and self.c_concat > 0:
|
349
|
+
self.c_connect += self.connect_all_nodes(rtol=1e-04,
|
350
|
+
atol=1e-03,
|
351
|
+
additional_nodes=nbr_nodes,
|
352
|
+
main=True)
|
353
|
+
|
354
|
+
if adjust:
|
355
|
+
self.adjust_all_points()
|
356
|
+
|
357
|
+
if delete and center:
|
358
|
+
self.set_minmax_radius()
|
359
|
+
|
360
|
+
timer.stop("-- Geometry initialised in %0.4f seconds --")
|
361
|
+
logger.debug("End Geometry(concatenated=%s, connected=%s)",
|
362
|
+
self.c_concat, self.c_connect)
|
363
|
+
|
349
364
|
def shaft(self):
|
350
365
|
"""returns shaft diameter if any"""
|
351
366
|
radius = []
|
@@ -379,8 +394,15 @@ class Geometry(object):
|
|
379
394
|
for n in self.g.nodes()}
|
380
395
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
381
396
|
|
397
|
+
def rotate_nodes(self, alpha, nodes):
|
398
|
+
T = np.array(((np.cos(alpha), -np.sin(alpha)),
|
399
|
+
(np.sin(alpha), np.cos(alpha))))
|
400
|
+
rotnodes = np.dot(T, np.asarray(nodes).T).T.tolist()
|
401
|
+
return rotnodes
|
402
|
+
|
382
403
|
def rotate(self, alpha):
|
383
404
|
"""rotates all objects by angle alpha"""
|
405
|
+
logger.debug("rotate geometry(%s)", alpha)
|
384
406
|
T = np.array(((np.cos(alpha), -np.sin(alpha)),
|
385
407
|
(np.sin(alpha), np.cos(alpha))))
|
386
408
|
for e in self.g.edges(data=True):
|
@@ -391,6 +413,7 @@ class Geometry(object):
|
|
391
413
|
mapping = {n: (round(r[0], ndec),
|
392
414
|
round(r[1], ndec))
|
393
415
|
for n, r in zip(self.g.nodes(), rotnodes)}
|
416
|
+
|
394
417
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
395
418
|
|
396
419
|
def check_geom(self, what):
|
@@ -449,12 +472,6 @@ class Geometry(object):
|
|
449
472
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
450
473
|
self.diameters = tuple([factor*d for d in self.diameters])
|
451
474
|
|
452
|
-
def find_nodes0(self, *points):
|
453
|
-
"""return closest nodes to points in arg within pickdist"""
|
454
|
-
return [tuple([round(int(x/self.atol+0.5)*self.atol, ndec)
|
455
|
-
for x in p])
|
456
|
-
for p in points]
|
457
|
-
|
458
475
|
def find_nodes(self, *points, **kwargs):
|
459
476
|
"""return closest nodes to points in arg within pickdist"""
|
460
477
|
n = []
|
@@ -475,21 +492,26 @@ class Geometry(object):
|
|
475
492
|
return [(round(p[0], ndec), round(p[1], ndec)) for p in points]
|
476
493
|
return n
|
477
494
|
|
478
|
-
def
|
479
|
-
"""return closest
|
495
|
+
def find_other_node(self, node, **kwargs):
|
496
|
+
"""return closest node to node in arg within pickdist"""
|
480
497
|
nodes = list(kwargs.get('g', self.g))
|
481
498
|
if nodes:
|
482
499
|
anodes = np.asarray(nodes)
|
483
500
|
# la.norm on numpy below 1.8 does not accept axis
|
484
|
-
c = anodes -
|
501
|
+
c = anodes - node
|
485
502
|
dist = np.sqrt(np.einsum('ij, ij->i', c, c))
|
486
|
-
# dist = la.norm(np.asarray(nodes) - p, axis=1)
|
487
503
|
idx = dist.argmin()
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
504
|
+
candidates = [(dist[i], nodes[i]) for i in range(len(dist))
|
505
|
+
if dist[i] < 0.01]
|
506
|
+
if not candidates:
|
507
|
+
return None
|
508
|
+
candidates.sort()
|
509
|
+
if len(candidates) > 1:
|
510
|
+
i = 0
|
511
|
+
d, n = candidates[0]
|
512
|
+
if d == 0.0:
|
513
|
+
d, n = candidates[1]
|
514
|
+
return n
|
493
515
|
return None
|
494
516
|
|
495
517
|
def find_the_node(self, p, **kwargs):
|
@@ -511,7 +533,7 @@ class Geometry(object):
|
|
511
533
|
paths = []
|
512
534
|
g = self.g.copy()
|
513
535
|
g.remove_edges_from(self.arcs())
|
514
|
-
while
|
536
|
+
while self.number_of_edges() > 0:
|
515
537
|
p = single_path(g.edges())
|
516
538
|
g.remove_edges_from(p)
|
517
539
|
# rearrange sequence to make it contiguous:
|
@@ -545,6 +567,69 @@ class Geometry(object):
|
|
545
567
|
return n
|
546
568
|
return []
|
547
569
|
|
570
|
+
def add_element(self, e, rtol, atol):
|
571
|
+
n = self.find_nodes(e.start(), e.end())
|
572
|
+
try:
|
573
|
+
self.add_or_join_edge(n[0], n[1], e, rtol=rtol, atol=atol)
|
574
|
+
except Exception as ex:
|
575
|
+
logger.warn("EXCEPTION in add_element: %s", ex)
|
576
|
+
|
577
|
+
def add_or_join_edge(self, n1, n2, entity, rtol=1e-03, atol=1e-03):
|
578
|
+
""" adds a new entity to graph or joins entity with existing
|
579
|
+
geom: Geometry
|
580
|
+
n1, n2: nodes
|
581
|
+
entity
|
582
|
+
"""
|
583
|
+
if n1 == n2:
|
584
|
+
logger.debug(
|
585
|
+
"add_or_join_edge: Tiny element with same node on both sides ignored: %s", n1)
|
586
|
+
logger.debug(
|
587
|
+
"add_or_join_edge: -- element: %s", entity)
|
588
|
+
return
|
589
|
+
|
590
|
+
e = self.get_edge_element(n1, n2)
|
591
|
+
if not e: # no duplicates
|
592
|
+
self.add_edge(n1, n2, entity)
|
593
|
+
return
|
594
|
+
|
595
|
+
logger.debug("add_or_join_edge: Duplicate connection: %s <--> %s", n1, n2)
|
596
|
+
if is_Line(e):
|
597
|
+
if is_Line(entity):
|
598
|
+
logger.debug("add_or_join_edge: Duplicate Lines ignored")
|
599
|
+
return # its ok
|
600
|
+
|
601
|
+
if is_Arc(e):
|
602
|
+
if is_Arc(entity):
|
603
|
+
if points_are_close(e.center, entity.center, rtol=rtol, atol=atol):
|
604
|
+
if points_are_close(e.p1, entity.p1):
|
605
|
+
logger.debug("add_or_join_edge: Duplicate Arcs ignored")
|
606
|
+
return # its ok
|
607
|
+
|
608
|
+
if is_Circle(entity):
|
609
|
+
if is_Circle(e):
|
610
|
+
logger.debug("add_or_join_edge: Duplicate Circle ignored")
|
611
|
+
return # its ok
|
612
|
+
|
613
|
+
if is_Circle(entity) or is_Circle(e):
|
614
|
+
e1, e2 = entity.cut_into_halves()
|
615
|
+
logger.debug("add_or_join_edge: Element near circle is cut into halves")
|
616
|
+
self.add_element(e1, rtol, atol)
|
617
|
+
self.add_element(e2, rtol, atol)
|
618
|
+
return # halves installed
|
619
|
+
|
620
|
+
m1 = e.center_of_connection()
|
621
|
+
m2 = entity.center_of_connection()
|
622
|
+
logger.debug("add_or_join_edge: midpoints: %s -- %s", m1, m2)
|
623
|
+
if points_are_close(m1, m2, rtol, 1e-2):
|
624
|
+
logger.debug("add_or_join_edge: Elements are close together")
|
625
|
+
return # ok
|
626
|
+
|
627
|
+
e1, e2 = entity.cut_into_halves()
|
628
|
+
logger.debug("add_or_join_edge: cut into halves")
|
629
|
+
self.add_element(e1, rtol, atol)
|
630
|
+
self.add_element(e2, rtol, atol)
|
631
|
+
return # halves installed
|
632
|
+
|
548
633
|
def add_edge(self, n1, n2, entity):
|
549
634
|
if points_are_close(n1, n2):
|
550
635
|
logger.debug("WARNING in add_edge(): Points of %s are close together",
|
@@ -552,10 +637,18 @@ class Geometry(object):
|
|
552
637
|
logger.debug(" n1 = %s, n2 = %s", n1, n2)
|
553
638
|
logger.debug(" p1 = %s, p2 = %s", entity.p1, entity.p2)
|
554
639
|
|
640
|
+
if self.has_edge(n1, n2):
|
641
|
+
logger.warning("FATAL ERROR: Duplicates in add_edge(%s, %s)", n1, n2)
|
642
|
+
|
555
643
|
entity.set_nodes(n1, n2)
|
556
644
|
logger.debug("add_edge %s - %s (%s)", n1, n2, entity.classname())
|
557
645
|
self.g.add_edge(n1, n2, object=entity)
|
558
646
|
|
647
|
+
def has_edge(self, n1, n2):
|
648
|
+
if self.g.get_edge_data(n1, n2):
|
649
|
+
return True
|
650
|
+
return False
|
651
|
+
|
559
652
|
def get_edge(self, eg):
|
560
653
|
return [[e[0], e[1], e[2]['object']] for e in self.g.edges(data=True)
|
561
654
|
if e[2]['object'] is eg]
|
@@ -574,6 +667,8 @@ class Geometry(object):
|
|
574
667
|
def _remove_edge(self, n1, n2):
|
575
668
|
logger.debug("remove_edge %s - %s", n1, n2)
|
576
669
|
self.g.remove_edge(n1, n2)
|
670
|
+
self._remove_node(n1)
|
671
|
+
self._remove_node(n2)
|
577
672
|
|
578
673
|
def remove_edge(self, edge):
|
579
674
|
e = self.get_edge(edge)
|
@@ -587,16 +682,21 @@ class Geometry(object):
|
|
587
682
|
for e in edges:
|
588
683
|
self.remove_edge(e)
|
589
684
|
|
685
|
+
def _remove_node(self, n):
|
686
|
+
for nbr in self.g.neighbors(n):
|
687
|
+
return
|
688
|
+
try:
|
689
|
+
self.g.remove_node(n)
|
690
|
+
except nx.NetworkXError:
|
691
|
+
logger.warning("WARNING: remove node %s failed", n)
|
692
|
+
|
590
693
|
def add_line(self, n1, n2, color=None, linestyle=None):
|
591
694
|
line = Line(Element(start=n1, end=n2),
|
592
695
|
color=color,
|
593
696
|
linestyle=linestyle)
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
line,
|
598
|
-
self.rtol,
|
599
|
-
self.atol)
|
697
|
+
self.add_element(line,
|
698
|
+
rtol=self.rtol,
|
699
|
+
atol=self.atol)
|
600
700
|
|
601
701
|
def add_arc(self, n1, n2, center, radius, color=None, linestyle=None):
|
602
702
|
angle_n1 = alpha_line(center, n1)
|
@@ -607,18 +707,20 @@ class Geometry(object):
|
|
607
707
|
end_angle=angle_n2*180/np.pi),
|
608
708
|
color=color,
|
609
709
|
linestyle=linestyle)
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
self.atol)
|
616
|
-
|
617
|
-
def elements(self, type):
|
710
|
+
self.add_element(arc,
|
711
|
+
rtol=self.rtol,
|
712
|
+
atol=self.atol)
|
713
|
+
|
714
|
+
def elements(self, type=Shape):
|
618
715
|
"""return lists of objects"""
|
619
716
|
return [e[2]['object'] for e in self.g.edges(data=True)
|
620
717
|
if isinstance(e[2]['object'], type)]
|
621
718
|
|
719
|
+
def elements_and_nodes(self, type=Shape):
|
720
|
+
"""return lists of objects"""
|
721
|
+
return [(e[0], e[1], e[2]['object']) for e in self.g.edges(data=True)
|
722
|
+
if isinstance(e[2]['object'], type)]
|
723
|
+
|
622
724
|
def arcs(self):
|
623
725
|
"""return lists of arcs"""
|
624
726
|
return self.elements(Arc)
|
@@ -642,12 +744,9 @@ class Geometry(object):
|
|
642
744
|
for p1, p2 in rem_lines:
|
643
745
|
self._remove_edge(p1, p2)
|
644
746
|
for new_ln in new_lines:
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
new_ln,
|
649
|
-
self.rtol,
|
650
|
-
self.atol)
|
747
|
+
self.add_element(new_ln,
|
748
|
+
rtol=self.rtol,
|
749
|
+
atol=self.atol)
|
651
750
|
|
652
751
|
def circles(self):
|
653
752
|
"""return list of circle nodes"""
|
@@ -658,8 +757,15 @@ class Geometry(object):
|
|
658
757
|
for n in self.g.nodes():
|
659
758
|
yield n
|
660
759
|
|
661
|
-
def get_nodes(self):
|
662
|
-
|
760
|
+
def get_nodes(self, num_of_nbrs=[]):
|
761
|
+
if num_of_nbrs:
|
762
|
+
nodes = []
|
763
|
+
for n in self.g.nodes():
|
764
|
+
nbr_list = [nbr for nbr in self.g.neighbors(n)]
|
765
|
+
if len(nbr_list) in num_of_nbrs:
|
766
|
+
nodes.append(n)
|
767
|
+
else:
|
768
|
+
nodes = [n for n in self.g.nodes()]
|
663
769
|
return nodes
|
664
770
|
|
665
771
|
def virtual_nodes(self):
|
@@ -668,14 +774,25 @@ class Geometry(object):
|
|
668
774
|
nodes += e.get_nodes()
|
669
775
|
return nodes
|
670
776
|
|
777
|
+
def get_neighbors(self, n):
|
778
|
+
return [nbr for nbr in self.g.neighbors(n)]
|
779
|
+
|
671
780
|
def angle_nodes(self, center, angle, rtol, atol):
|
781
|
+
if np.isclose(abs(angle), np.pi, rtol, atol):
|
782
|
+
angle_func = positive_angle
|
783
|
+
else:
|
784
|
+
angle_func = normalise_angle
|
785
|
+
angle = angle_func(angle)
|
786
|
+
|
672
787
|
nodes = []
|
673
788
|
for n in self.g.nodes():
|
674
789
|
if points_are_close(center, n, rtol, atol):
|
675
790
|
# Da gibt es keinen brauchbaren Winkel
|
676
791
|
nodes.append(n)
|
677
|
-
|
678
|
-
|
792
|
+
else:
|
793
|
+
angle_line = angle_func(alpha_line(center, n))
|
794
|
+
if np.isclose(angle, angle_line, rtol, atol):
|
795
|
+
nodes.append(n)
|
679
796
|
return nodes
|
680
797
|
|
681
798
|
def radius_nodes(self, center, radius, rtol, atol):
|
@@ -747,7 +864,10 @@ class Geometry(object):
|
|
747
864
|
else:
|
748
865
|
p = (self.min_radius, 0.0)
|
749
866
|
cp = self.start_corners[0]
|
750
|
-
if points_are_close(p, cp, atol=
|
867
|
+
if points_are_close(p, cp, rtol=1e-2, atol=1e-1):
|
868
|
+
if points_are_close(p, cp, rtol=1e-3, atol=1e-2):
|
869
|
+
logger.debug("get_start_airgap_corner: critical")
|
870
|
+
logger.debug(" -- soll: %s, ist: %s", p, cp)
|
751
871
|
return cp, True
|
752
872
|
return p, False
|
753
873
|
|
@@ -758,7 +878,11 @@ class Geometry(object):
|
|
758
878
|
else:
|
759
879
|
p = point(self.center, self.min_radius, self.alfa, ndec)
|
760
880
|
cp = self.end_corners[0]
|
761
|
-
|
881
|
+
logger.debug("End Airgap Corner: %s is %s", p, cp)
|
882
|
+
if points_are_close(p, cp, rtol=1e-2, atol=1e-1):
|
883
|
+
if points_are_close(p, cp, rtol=1e-3, atol=1e-2):
|
884
|
+
logger.debug("get_end_airgap_corner: critical")
|
885
|
+
logger.debug(" -- soll: %s, ist: %s", p, cp)
|
762
886
|
return cp, True
|
763
887
|
return p, False
|
764
888
|
|
@@ -798,6 +922,7 @@ class Geometry(object):
|
|
798
922
|
atol = 1e-3
|
799
923
|
|
800
924
|
logger.debug("begin repair_hull_line(center=%s, angle=%s)", center, angle)
|
925
|
+
[logger.debug(" --> Corner %s", c) for c in corners]
|
801
926
|
|
802
927
|
if len(corners) < 2:
|
803
928
|
# no hull without more than 1 corners
|
@@ -840,8 +965,12 @@ class Geometry(object):
|
|
840
965
|
radius=el.radius,
|
841
966
|
start_angle=alpha_mid*180/np.pi,
|
842
967
|
end_angle=alpha_end*180/np.pi))
|
843
|
-
self.
|
844
|
-
|
968
|
+
self.add_element(a1,
|
969
|
+
rtol=self.rtol,
|
970
|
+
atol=self.atol)
|
971
|
+
self.add_element(a2,
|
972
|
+
rtol=self.rtol,
|
973
|
+
atol=self.atol)
|
845
974
|
else:
|
846
975
|
clist = []
|
847
976
|
if clist_p1:
|
@@ -850,18 +979,12 @@ class Geometry(object):
|
|
850
979
|
clist = [c for c in clist_p2]
|
851
980
|
[corner.set_keep_node() for corner in clist]
|
852
981
|
|
853
|
-
try:
|
854
|
-
[self.g.remove_node(c.point())
|
855
|
-
for c in corners if not c.keep_node()]
|
856
|
-
except Exception as e:
|
857
|
-
logger.warn("Warning: %s", e)
|
858
|
-
|
859
982
|
# Rebuild Corner-list after correction
|
860
983
|
center_added, corners = self.get_corner_list(center, angle, rtol, atol)
|
861
984
|
for c in corners:
|
862
985
|
logger.debug("Correct Corner: %s", c)
|
863
986
|
|
864
|
-
if with_center:
|
987
|
+
if with_center or self.with_center_node:
|
865
988
|
c_corner = Corner(center, tuple(center))
|
866
989
|
if c_corner not in corners:
|
867
990
|
corners.append(c_corner)
|
@@ -871,7 +994,9 @@ class Geometry(object):
|
|
871
994
|
p1 = corners[0].point()
|
872
995
|
for c in corners[1:]:
|
873
996
|
p2 = c.point()
|
874
|
-
self.
|
997
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
998
|
+
rtol=self.rtol,
|
999
|
+
atol=self.atol)
|
875
1000
|
p1 = p2
|
876
1001
|
|
877
1002
|
self.set_minmax_radius()
|
@@ -906,14 +1031,18 @@ class Geometry(object):
|
|
906
1031
|
c_min.is_new_point = True
|
907
1032
|
p1 = c_min.point()
|
908
1033
|
p2 = c_first.point()
|
909
|
-
self.
|
1034
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
1035
|
+
rtol=self.rtol,
|
1036
|
+
atol=self.atol)
|
910
1037
|
|
911
1038
|
c_last = corners[len(corners)-1]
|
912
1039
|
if not c_max.is_same_corner(c_last):
|
913
1040
|
c_max.is_new_point = True
|
914
1041
|
p2 = c_max.point()
|
915
1042
|
p1 = c_last.point()
|
916
|
-
self.
|
1043
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
1044
|
+
rtol=self.rtol,
|
1045
|
+
atol=self.atol)
|
917
1046
|
logger.debug("end complete_hull_line")
|
918
1047
|
return (c_min, c_max)
|
919
1048
|
|
@@ -928,10 +1057,12 @@ class Geometry(object):
|
|
928
1057
|
nodes_sorted.sort()
|
929
1058
|
p = nodes_sorted[0][1]
|
930
1059
|
angle_p = alpha_line(self.center, p)
|
931
|
-
self.
|
932
|
-
|
933
|
-
|
934
|
-
|
1060
|
+
arc = Arc(Element(center=self.center, radius=radius,
|
1061
|
+
start_angle=startangle*180/np.pi,
|
1062
|
+
end_angle=angle_p*180/np.pi))
|
1063
|
+
self.add_element(arc,
|
1064
|
+
rtol=self.rtol,
|
1065
|
+
atol=self.atol)
|
935
1066
|
|
936
1067
|
if endcorner.is_new_point:
|
937
1068
|
end_p = endcorner.point()
|
@@ -940,10 +1071,12 @@ class Geometry(object):
|
|
940
1071
|
inx = len(nodes_sorted)-1
|
941
1072
|
p = nodes_sorted[inx][1]
|
942
1073
|
angle_p = alpha_line(self.center, p)
|
943
|
-
self.
|
944
|
-
|
945
|
-
|
946
|
-
|
1074
|
+
arc = Arc(Element(center=self.center, radius=radius,
|
1075
|
+
start_angle=angle_p*180/np.pi,
|
1076
|
+
end_angle=endangle*180/np.pi))
|
1077
|
+
self.add_element(p, end_p, arc,
|
1078
|
+
rtol=self.rtol,
|
1079
|
+
atol=self.atol)
|
947
1080
|
|
948
1081
|
def get_corner_nodes(self, center, angle):
|
949
1082
|
rtol = 1e-4
|
@@ -954,313 +1087,17 @@ class Geometry(object):
|
|
954
1087
|
return () # not enough corners
|
955
1088
|
return (corners[0].point(), corners[len(corners)-1].point())
|
956
1089
|
|
1090
|
+
def set_start_corners(self, center, angle):
|
1091
|
+
self.start_corners = self.get_corner_nodes(center, angle)
|
1092
|
+
|
1093
|
+
def set_end_corners(self, center, angle):
|
1094
|
+
self.end_corners = self.get_corner_nodes(center, angle)
|
1095
|
+
|
957
1096
|
def get_angle(self, alpha1, alpha2):
|
958
1097
|
if np.isclose(alpha1, alpha2, 0.001, 0.001):
|
959
1098
|
return 0.0
|
960
1099
|
return alpha_angle(alpha1, alpha2)
|
961
1100
|
|
962
|
-
def get_edge_neighbors_list(self, alpha, info):
|
963
|
-
n1 = info['n1']
|
964
|
-
n2 = info['n2']
|
965
|
-
|
966
|
-
nbrs = [n for n in self.g.neighbors(n2)
|
967
|
-
if not (points_are_close(n, n1) or points_are_close(n, n2))]
|
968
|
-
if len(nbrs) == 0:
|
969
|
-
logger.debug(" FATAL: no neighbors of %s available ???", n2)
|
970
|
-
return []
|
971
|
-
|
972
|
-
angles = []
|
973
|
-
for c, n in enumerate(nbrs):
|
974
|
-
info_next = self.get_edge_info(n2, n)
|
975
|
-
angle = self.get_angle(alpha, info_next['alpha_start'])
|
976
|
-
angles.append((angle, c, info_next))
|
977
|
-
|
978
|
-
info_rev = self.get_reverse_edge_info(info)
|
979
|
-
angle = self.get_angle(alpha, info_rev['alpha_start'])
|
980
|
-
angles.append((angle, c+1, info_rev))
|
981
|
-
angles.sort(reverse=True)
|
982
|
-
return angles
|
983
|
-
|
984
|
-
def is_lefthand_edge(self, alpha, info1, info2):
|
985
|
-
logger.debug(" begin of is_lefthand_edge()")
|
986
|
-
angle1 = self.get_angle(alpha, info1['alpha_start'])
|
987
|
-
angle2 = self.get_angle(alpha, info2['alpha_start'])
|
988
|
-
if not np.isclose(angle1, angle2, 0.005, 0.005):
|
989
|
-
logger.debug(" UNEXPECTED DIFFERENT ANGLES")
|
990
|
-
return angle1 > angle2
|
991
|
-
|
992
|
-
alpha_start = info1['alpha_start']
|
993
|
-
|
994
|
-
if self.is_edge_arc(info1):
|
995
|
-
if self.is_edge_arc(info2):
|
996
|
-
logger.debug(" ARC - ARC")
|
997
|
-
|
998
|
-
i1_dist = distance(info1['n1'], info1['n2'])
|
999
|
-
i2_dist = distance(info2['n1'], info2['n2'])
|
1000
|
-
min_dist = min(i1_dist, i2_dist) / 1.5
|
1001
|
-
|
1002
|
-
circ = Circle(Element(center=info1['n1'],
|
1003
|
-
radius=min_dist))
|
1004
|
-
pt = info1['element'].intersect_circle(circ)
|
1005
|
-
if len(pt) != 1:
|
1006
|
-
logger.debug("WARNING: intersect problem at %s",
|
1007
|
-
info1['n1'])
|
1008
|
-
i1_alpha = info1['alpha_n2']
|
1009
|
-
else:
|
1010
|
-
i1_alpha = alpha_line(info1['n1'], pt[0])
|
1011
|
-
i1_angle = self.get_angle(alpha_start, i1_alpha)
|
1012
|
-
|
1013
|
-
circ = Circle(Element(center=info2['n1'],
|
1014
|
-
radius=min_dist))
|
1015
|
-
pt = info2['element'].intersect_circle(circ)
|
1016
|
-
if len(pt) != 1:
|
1017
|
-
logger.debug("WARNING: intersect problem at %s",
|
1018
|
-
info2['n1'])
|
1019
|
-
i2_alpha = info2['alpha_n2']
|
1020
|
-
else:
|
1021
|
-
i2_alpha = alpha_line(info2['n1'], pt[0])
|
1022
|
-
i2_angle = self.get_angle(alpha_start, i2_alpha)
|
1023
|
-
|
1024
|
-
rslt = normalise_angle(i1_angle) > normalise_angle(i2_angle)
|
1025
|
-
logger.debug(" end of is_lefthand_edge() = %s",
|
1026
|
-
rslt)
|
1027
|
-
return rslt
|
1028
|
-
|
1029
|
-
logger.debug(" ARC - LINE")
|
1030
|
-
|
1031
|
-
e1 = info1['element']
|
1032
|
-
d2 = distance(e1.center, info2['n2'])
|
1033
|
-
if not np.isclose(e1.radius, d2, 0.005, 0.005):
|
1034
|
-
angle1 = self.get_angle(alpha, info1['alpha_n2'])
|
1035
|
-
angle = alpha_angle(angle1, angle2)
|
1036
|
-
logger.debug(" NOT close together")
|
1037
|
-
rslt = greater(angle, np.pi)
|
1038
|
-
logger.debug(" end of is_lefthand_edge() = %s", rslt)
|
1039
|
-
return rslt
|
1040
|
-
|
1041
|
-
next_info2 = self.next_edge_lefthand_side(info2)
|
1042
|
-
if not next_info2:
|
1043
|
-
logger.debug("FATAL ERROR")
|
1044
|
-
raise ValueError("FATAL ERROR: no edge found")
|
1045
|
-
|
1046
|
-
return self.is_lefthand_edge(alpha, info1, next_info2)
|
1047
|
-
|
1048
|
-
if not self.is_edge_arc(info2):
|
1049
|
-
# two overlapping lines
|
1050
|
-
logger.debug(" end of is_lefthand_edge(): overlap")
|
1051
|
-
return True
|
1052
|
-
|
1053
|
-
logger.debug(" LINE - ARC")
|
1054
|
-
|
1055
|
-
rslt = not self.is_lefthand_edge(alpha, info2, info1)
|
1056
|
-
logger.debug(" end of is_lefthand_edge() = %s", rslt)
|
1057
|
-
return rslt
|
1058
|
-
|
1059
|
-
def next_edge_lefthand_side(self, info_curr): # current
|
1060
|
-
alpha = normalise_angle(info_curr['alpha_n2'] + np.pi)
|
1061
|
-
logger.debug(" next_edge_lefthand_side( alpha=%s )", alpha)
|
1062
|
-
|
1063
|
-
nbrs = self.get_edge_neighbors_list(alpha, info_curr)
|
1064
|
-
if len(nbrs) == 0:
|
1065
|
-
logger.debug(" no neighbors available ???")
|
1066
|
-
return None # unexpected end
|
1067
|
-
|
1068
|
-
if len(nbrs) < 3:
|
1069
|
-
for a, c, info_next in nbrs:
|
1070
|
-
if not info_next['reverse']:
|
1071
|
-
return info_next
|
1072
|
-
raise ValueError("FATAL ERROR in next_edge_lefthand_side() !!")
|
1073
|
-
|
1074
|
-
logger.debug(" POINT WITH %s NEIGHBORS", len(nbrs)-1)
|
1075
|
-
|
1076
|
-
f_angle, f_c, f_info_next = nbrs[0]
|
1077
|
-
f_info_next['angle'] = f_angle
|
1078
|
-
|
1079
|
-
for n_angle, n_c, n_info_next in nbrs[1:]:
|
1080
|
-
n_info_next['angle'] = n_angle
|
1081
|
-
if np.isclose(f_angle, n_angle, 0.01, 0.01):
|
1082
|
-
logger.debug(" SAME DIRECTION")
|
1083
|
-
# ACHTUNG
|
1084
|
-
if self.is_lefthand_edge(alpha, f_info_next, n_info_next):
|
1085
|
-
logger.debug(" == first is on the left side")
|
1086
|
-
angle = self.get_angle(alpha,
|
1087
|
-
n_info_next['alpha_start'] - 0.01)
|
1088
|
-
n_info_next['angle'] = angle
|
1089
|
-
else:
|
1090
|
-
logger.debug(" == next is on the left side")
|
1091
|
-
angle = self.get_angle(alpha,
|
1092
|
-
f_info_next['alpha_start'] - 0.01)
|
1093
|
-
f_info_next['angle'] = angle
|
1094
|
-
|
1095
|
-
f_angle = n_angle
|
1096
|
-
f_info_next = n_info_next
|
1097
|
-
|
1098
|
-
nbrs2 = [(e['angle'], c, e) for a, c, e in nbrs
|
1099
|
-
if not e['reverse']]
|
1100
|
-
nbrs2.sort(reverse=True)
|
1101
|
-
return nbrs2[0][2]
|
1102
|
-
|
1103
|
-
def get_edge_info(self, n1, n2):
|
1104
|
-
e_dict = self.g.get_edge_data(n1, n2)
|
1105
|
-
if not e_dict:
|
1106
|
-
raise ValueError("Fatal: no edge-data found from {} to {}"
|
1107
|
-
.format(n1, n2))
|
1108
|
-
|
1109
|
-
e = e_dict.get('object', None)
|
1110
|
-
if not e:
|
1111
|
-
raise ValueError("Fatal: no object found from {} to {}"
|
1112
|
-
.format(n1, n2))
|
1113
|
-
|
1114
|
-
x = e.get_node_number(n1)
|
1115
|
-
alpha_n1 = e.get_alpha(n1)
|
1116
|
-
|
1117
|
-
info = {'n1': n1,
|
1118
|
-
'n2': n2,
|
1119
|
-
'data': e_dict,
|
1120
|
-
'element': e,
|
1121
|
-
'x': x,
|
1122
|
-
'alpha_n1': alpha_n1,
|
1123
|
-
'alpha_n2': e.get_alpha(n2),
|
1124
|
-
'alpha_start': normalise_angle(alpha_n1 + np.pi),
|
1125
|
-
'tracked': e_dict.get(x, False),
|
1126
|
-
'reverse': False}
|
1127
|
-
return info
|
1128
|
-
|
1129
|
-
def get_reverse_edge_info(self, info):
|
1130
|
-
alpha_n1 = info['alpha_n2']
|
1131
|
-
rev_info = {'n1': info['n2'],
|
1132
|
-
'n2': info['n1'],
|
1133
|
-
'data': info['data'],
|
1134
|
-
'element': info['element'],
|
1135
|
-
'x': 0,
|
1136
|
-
'alpha_n1': alpha_n1,
|
1137
|
-
'alpha_n2': info['alpha_n1'],
|
1138
|
-
'alpha_start': normalise_angle(alpha_n1 + np.pi),
|
1139
|
-
'tracked': False,
|
1140
|
-
'reverse': True}
|
1141
|
-
return rev_info
|
1142
|
-
|
1143
|
-
def is_edge_arc(self, info):
|
1144
|
-
return isinstance(info['element'], Arc)
|
1145
|
-
|
1146
|
-
def log_edge_info(self, info):
|
1147
|
-
logger.debug(' node1 = %s', info['n1'])
|
1148
|
-
logger.debug(' node2 = %s', info['n2'])
|
1149
|
-
logger.debug(' x = %s', info['x'])
|
1150
|
-
logger.debug(' lock = (%s, %s, %s)',
|
1151
|
-
info['data'].get(0, False),
|
1152
|
-
info['data'].get(1, False),
|
1153
|
-
info['data'].get(2, False))
|
1154
|
-
|
1155
|
-
def set_edge_tracked(self, info):
|
1156
|
-
x = info['x']
|
1157
|
-
info['data'][x] = True # footprint
|
1158
|
-
|
1159
|
-
def get_new_area(self, start_n1, start_n2, solo):
|
1160
|
-
info_curr = self.get_edge_info(start_n1, start_n2)
|
1161
|
-
|
1162
|
-
area = []
|
1163
|
-
result = {'area': area,
|
1164
|
-
'elements': 1,
|
1165
|
-
'msg': "<undefined>",
|
1166
|
-
'reverse': False,
|
1167
|
-
'ok': False}
|
1168
|
-
area.append(info_curr['element'])
|
1169
|
-
|
1170
|
-
if info_curr['tracked']:
|
1171
|
-
result['msg'] = ("<== area already tracked (%s) ***",
|
1172
|
-
info_curr['x'])
|
1173
|
-
result['area'] = None
|
1174
|
-
return result
|
1175
|
-
|
1176
|
-
logger.debug('==> start of get_new_area()')
|
1177
|
-
self.log_edge_info(info_curr)
|
1178
|
-
self.set_edge_tracked(info_curr)
|
1179
|
-
|
1180
|
-
e = info_curr['element']
|
1181
|
-
if (isinstance(e, Circle) and not isinstance(e, Arc)):
|
1182
|
-
result['msg'] = "area is a circle !!"
|
1183
|
-
logger.debug("<== %s", result['msg'])
|
1184
|
-
e_dict = info_curr['data']
|
1185
|
-
e_dict[1] = True # footprint
|
1186
|
-
e_dict[2] = True # footprint
|
1187
|
-
result['ok'] = True
|
1188
|
-
return result
|
1189
|
-
|
1190
|
-
logger.debug("***** EDGE %s *****", 1)
|
1191
|
-
info_next = self.next_edge_lefthand_side(info_curr)
|
1192
|
-
if not info_next:
|
1193
|
-
result['msg'] = ("dead end ({}, {})"
|
1194
|
-
.format(info_curr['n1'], info_curr['n2']))
|
1195
|
-
logger.debug("<== %s", result['msg'])
|
1196
|
-
return result
|
1197
|
-
self.log_edge_info(info_next)
|
1198
|
-
|
1199
|
-
prev_n1 = info_curr['n1']
|
1200
|
-
next_n1 = info_next['n1']
|
1201
|
-
next_n2 = info_next['n2']
|
1202
|
-
|
1203
|
-
alpha = normalise_angle(alpha_points(prev_n1,
|
1204
|
-
next_n1,
|
1205
|
-
next_n2))
|
1206
|
-
|
1207
|
-
c = 1
|
1208
|
-
while not (nodes_are_equal(next_n1, start_n1) and
|
1209
|
-
nodes_are_equal(next_n2, start_n2)):
|
1210
|
-
c += 1
|
1211
|
-
if c > self.num_edges * 2:
|
1212
|
-
logger.error("FATAL: *** over %s elements in area ? ***",
|
1213
|
-
self.num_edges)
|
1214
|
-
plot_area(area)
|
1215
|
-
sys.exit(1)
|
1216
|
-
|
1217
|
-
area.append(info_next['element'])
|
1218
|
-
|
1219
|
-
if info_next['tracked']:
|
1220
|
-
result['msg'] = ("FATAL: area already tracked ({}) ***"
|
1221
|
-
.format(info_next['x']))
|
1222
|
-
logger.debug("<== %s", result['msg'])
|
1223
|
-
result['elements'] = c
|
1224
|
-
return result
|
1225
|
-
|
1226
|
-
self.set_edge_tracked(info_next)
|
1227
|
-
|
1228
|
-
info_curr = info_next
|
1229
|
-
logger.debug("***** EDGE %s *****", c)
|
1230
|
-
info_next = self.next_edge_lefthand_side(info_curr)
|
1231
|
-
if not info_next:
|
1232
|
-
result['msg'] = ("<== dead end ({},{})"
|
1233
|
-
.format(info_curr['n1'], info_curr['n2']))
|
1234
|
-
logger.debug("<== %s", result['msg'])
|
1235
|
-
result['elements'] = c
|
1236
|
-
return result
|
1237
|
-
self.log_edge_info(info_next)
|
1238
|
-
|
1239
|
-
prev_n1 = info_curr['n1']
|
1240
|
-
next_n1 = info_next['n1']
|
1241
|
-
next_n2 = info_next['n2']
|
1242
|
-
|
1243
|
-
a = normalise_angle(alpha_points(prev_n1,
|
1244
|
-
next_n1,
|
1245
|
-
next_n2))
|
1246
|
-
alpha += a
|
1247
|
-
|
1248
|
-
logger.debug(" END OF get_new_area")
|
1249
|
-
|
1250
|
-
if alpha < 0.0:
|
1251
|
-
result['msg'] = ("turn left expected, but it turned right ({})"
|
1252
|
-
.format(alpha))
|
1253
|
-
logger.debug("<== %s", result['msg'])
|
1254
|
-
result['elements'] = c
|
1255
|
-
result['reverse'] = True
|
1256
|
-
return result
|
1257
|
-
|
1258
|
-
result['msg'] = "area found !!"
|
1259
|
-
logger.debug("<== %s", result['msg'])
|
1260
|
-
result['elements'] = c
|
1261
|
-
result['ok'] = True
|
1262
|
-
return result
|
1263
|
-
|
1264
1101
|
def set_edge_attributes(self):
|
1265
1102
|
if nxversion == 1:
|
1266
1103
|
nx.set_edge_attributes(self.g, 0, True)
|
@@ -1271,7 +1108,7 @@ class Geometry(object):
|
|
1271
1108
|
nx.set_edge_attributes(self.g, False, 1)
|
1272
1109
|
nx.set_edge_attributes(self.g, False, 2)
|
1273
1110
|
|
1274
|
-
def create_list_of_areas(self,
|
1111
|
+
def create_list_of_areas(self, main=False):
|
1275
1112
|
""" return list of areas for each node and their neighbors
|
1276
1113
|
"""
|
1277
1114
|
if len(self.area_list) > 0:
|
@@ -1280,47 +1117,9 @@ class Geometry(object):
|
|
1280
1117
|
return
|
1281
1118
|
|
1282
1119
|
areabuilder = AreaBuilder(geom=self)
|
1283
|
-
areabuilder.create_list_of_areas(main=
|
1120
|
+
areabuilder.create_list_of_areas(main=main)
|
1284
1121
|
self.area_list = areabuilder.area_list
|
1285
|
-
|
1286
|
-
|
1287
|
-
def append(area_list, a):
|
1288
|
-
for area in area_list:
|
1289
|
-
if area.is_identical(a):
|
1290
|
-
return
|
1291
|
-
area_list.append(a)
|
1292
|
-
|
1293
|
-
logger.debug("create new area list")
|
1294
|
-
self.set_edge_attributes()
|
1295
|
-
|
1296
|
-
crunched = 0
|
1297
|
-
for n in self.g.nodes():
|
1298
|
-
if self.debug:
|
1299
|
-
print('.', end='', flush=True)
|
1300
|
-
|
1301
|
-
finished = False
|
1302
|
-
while not finished:
|
1303
|
-
finished = True
|
1304
|
-
nbrs = [nbr for nbr in self.g.neighbors(n)]
|
1305
|
-
for next_n in nbrs:
|
1306
|
-
result = self.get_new_area(n, next_n, len(nbrs) < 3)
|
1307
|
-
if result['ok']:
|
1308
|
-
area = result['area']
|
1309
|
-
a = Area(area, self.center, 0.0)
|
1310
|
-
logger.debug("Area %s found", a.identifier())
|
1311
|
-
if crunch:
|
1312
|
-
c = a.crunch_area(self)
|
1313
|
-
else:
|
1314
|
-
c = 0
|
1315
|
-
append(self.area_list, a)
|
1316
|
-
crunched += c
|
1317
|
-
if c > 0:
|
1318
|
-
# take care! may be there are new neighbors for n
|
1319
|
-
finished = False
|
1320
|
-
break
|
1321
|
-
|
1322
|
-
logger.debug("%s areas found and %s elements concatenated",
|
1323
|
-
len(self.area_list), crunched)
|
1122
|
+
logger.debug("area list created")
|
1324
1123
|
|
1325
1124
|
def list_of_areas(self):
|
1326
1125
|
self.create_list_of_areas()
|
@@ -1497,8 +1296,12 @@ class Geometry(object):
|
|
1497
1296
|
end_angle=alpha_end*180/np.pi))
|
1498
1297
|
if points_are_close(a.p1, a.p2, rtol=1e-02, atol=1e-02):
|
1499
1298
|
logger.debug("ATTENTION: creation of a tiny arc")
|
1299
|
+
logger.debug("-- %s", a)
|
1500
1300
|
a.set_attribute("tiny")
|
1501
|
-
|
1301
|
+
if points_are_close(a.p1, a.p2, rtol=1e-06, atol=1e-06):
|
1302
|
+
logger.debug("-- points are equal")
|
1303
|
+
else:
|
1304
|
+
new_elements.append(a)
|
1502
1305
|
alpha_start = alpha_end
|
1503
1306
|
p1 = p2
|
1504
1307
|
return new_elements
|
@@ -1594,7 +1397,8 @@ class Geometry(object):
|
|
1594
1397
|
append_inner=False,
|
1595
1398
|
append_outer=False,
|
1596
1399
|
delete_appendices=False,
|
1597
|
-
|
1400
|
+
concatenate=True,
|
1401
|
+
connect=True):
|
1598
1402
|
""" Die Funktion kopiert die Teile von Shape-Objekten, welche sich in
|
1599
1403
|
der durch die Parameter definierten Teilkreisfläche befinden.
|
1600
1404
|
"""
|
@@ -1608,6 +1412,8 @@ class Geometry(object):
|
|
1608
1412
|
atol = 1e-4
|
1609
1413
|
logger.debug(' -> rtol=%s, atol=%s', rtol, atol)
|
1610
1414
|
|
1415
|
+
self.with_center_node = self.find_the_node(self.center) is not None
|
1416
|
+
|
1611
1417
|
if is_same_angle(startangle, endangle):
|
1612
1418
|
start_line = Line(
|
1613
1419
|
Element(start=self.center,
|
@@ -1695,40 +1501,28 @@ class Geometry(object):
|
|
1695
1501
|
new_elements.append(arc)
|
1696
1502
|
p1 = p2
|
1697
1503
|
|
1698
|
-
|
1699
|
-
ok, new_elements = self.concatenate_tiny_elements(new_elements)
|
1700
|
-
if ok:
|
1701
|
-
split = True
|
1702
|
-
|
1703
|
-
if delete_appendices:
|
1704
|
-
center = []
|
1705
|
-
else:
|
1706
|
-
center = self.center
|
1504
|
+
center = self.center
|
1707
1505
|
|
1708
1506
|
if split:
|
1709
1507
|
logger.debug('new Geometry with split')
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
is_outer=self.is_outer)
|
1724
|
-
|
1725
|
-
if delete_appendices:
|
1726
|
-
geom.delete_all_appendices()
|
1727
|
-
geom.set_center(self.center)
|
1508
|
+
|
1509
|
+
geom = Geometry(new_elements,
|
1510
|
+
center=center,
|
1511
|
+
rtol=self.rtol,
|
1512
|
+
atol=self.atol,
|
1513
|
+
is_inner=self.is_inner,
|
1514
|
+
is_outer=self.is_outer,
|
1515
|
+
concatenate=concatenate,
|
1516
|
+
connect=connect,
|
1517
|
+
delete=delete_appendices,
|
1518
|
+
split=split)
|
1519
|
+
geom.with_center_node = self.with_center_node
|
1520
|
+
|
1728
1521
|
logger.debug('end copy_shape')
|
1729
1522
|
return geom
|
1730
1523
|
|
1731
1524
|
def copy_all_elements(self, alpha):
|
1525
|
+
logger.debug("begin copy_all_elements(alpha=%s)", alpha)
|
1732
1526
|
if alpha == 0.0:
|
1733
1527
|
T = None
|
1734
1528
|
else:
|
@@ -1764,19 +1558,25 @@ class Geometry(object):
|
|
1764
1558
|
el.transform(T, alpha, ndec)
|
1765
1559
|
all_el.append(el)
|
1766
1560
|
|
1767
|
-
logger.debug("copy_all_elements: %s lines, %s arcs, %s circles",
|
1561
|
+
logger.debug("end copy_all_elements: %s lines, %s arcs, %s circles",
|
1768
1562
|
lines, arcs, circles)
|
1769
|
-
|
1770
1563
|
return all_el
|
1771
1564
|
|
1772
|
-
def new_clone(self, new_elements,
|
1565
|
+
def new_clone(self, new_elements,
|
1566
|
+
split=False,
|
1567
|
+
concatenate=False,
|
1568
|
+
connect=False,
|
1569
|
+
adjust=False):
|
1773
1570
|
return Geometry(new_elements,
|
1774
1571
|
center=self.center,
|
1775
1572
|
rtol=self.rtol,
|
1776
1573
|
atol=self.atol,
|
1777
1574
|
is_inner=self.is_inner,
|
1778
1575
|
is_outer=self.is_outer,
|
1779
|
-
split=split
|
1576
|
+
split=split,
|
1577
|
+
concatenate=concatenate,
|
1578
|
+
connect=connect,
|
1579
|
+
adjust=adjust)
|
1780
1580
|
|
1781
1581
|
def is_new_angle(self, alpha_list, alpha):
|
1782
1582
|
for a in alpha_list:
|
@@ -1784,78 +1584,6 @@ class Geometry(object):
|
|
1784
1584
|
return False
|
1785
1585
|
return True
|
1786
1586
|
|
1787
|
-
def concatenate_arc_elements(self, el, elements):
|
1788
|
-
if not is_Arc(el):
|
1789
|
-
return False
|
1790
|
-
|
1791
|
-
def match(e1, e2):
|
1792
|
-
if e2.has_attribute("del"):
|
1793
|
-
return False
|
1794
|
-
if e2.has_attribute("tiny"):
|
1795
|
-
return False
|
1796
|
-
if not points_are_close(e1.center, e2.center):
|
1797
|
-
return False
|
1798
|
-
return np.isclose(e1.radius, e2.radius)
|
1799
|
-
|
1800
|
-
elmts = [(e.p1, e) for e in elements if is_Arc(e) and match(el, e)]
|
1801
|
-
elmts.sort()
|
1802
|
-
|
1803
|
-
ok = False
|
1804
|
-
for p, e in elmts:
|
1805
|
-
el_new = el.concatenate(None, None, e)
|
1806
|
-
if el_new:
|
1807
|
-
el.set_attribute("del")
|
1808
|
-
e.set_attribute("del")
|
1809
|
-
elements.append(el_new)
|
1810
|
-
el = el_new
|
1811
|
-
ok = True
|
1812
|
-
return ok
|
1813
|
-
|
1814
|
-
def concatenate_line_elements(self, el, elements):
|
1815
|
-
if not is_Line(el):
|
1816
|
-
return False
|
1817
|
-
|
1818
|
-
def match(e1, e2):
|
1819
|
-
if e2.has_attribute("del"):
|
1820
|
-
return False
|
1821
|
-
if e2.has_attribute("tiny"):
|
1822
|
-
return False
|
1823
|
-
return np.isclose(e1.m(999999.0), e2.m(999999.0))
|
1824
|
-
|
1825
|
-
elmts = [(e.p1, e) for e in elements if is_Line(e) and match(el, e)]
|
1826
|
-
elmts.sort()
|
1827
|
-
|
1828
|
-
ok = False
|
1829
|
-
for p, e in elmts:
|
1830
|
-
el_new = el.concatenate(None, None, e)
|
1831
|
-
if el_new:
|
1832
|
-
el.set_attribute("del")
|
1833
|
-
e.set_attribute("del")
|
1834
|
-
elements.append(el_new)
|
1835
|
-
el = el_new
|
1836
|
-
ok = True
|
1837
|
-
return ok
|
1838
|
-
|
1839
|
-
def concatenate_tiny_elements(self, new_elements):
|
1840
|
-
logger.debug("begin concatenate_tiny_elements")
|
1841
|
-
tiny_elements = [e for e in new_elements if e.has_attribute("tiny")]
|
1842
|
-
if not tiny_elements:
|
1843
|
-
logger.debug("end concatenate_tiny_elements: (%s elements)", 0)
|
1844
|
-
return False, new_elements
|
1845
|
-
|
1846
|
-
count = 0
|
1847
|
-
for e_tiny in tiny_elements:
|
1848
|
-
if is_Line(e_tiny):
|
1849
|
-
if self.concatenate_line_elements(e_tiny, new_elements):
|
1850
|
-
count += 1
|
1851
|
-
elif is_Arc(e_tiny):
|
1852
|
-
if self.concatenate_arc_elements(e_tiny, new_elements):
|
1853
|
-
count += 1
|
1854
|
-
|
1855
|
-
new_list = [e for e in new_elements if not e.has_attribute("del")]
|
1856
|
-
logger.debug("end concatenate_tiny_elements: (%s elements)", count)
|
1857
|
-
return count>0, new_list
|
1858
|
-
|
1859
1587
|
def find_symmetry(self, radius,
|
1860
1588
|
startangle, endangle, sym_tolerance):
|
1861
1589
|
arealist = self.list_of_areas()
|
@@ -2082,6 +1810,25 @@ class Geometry(object):
|
|
2082
1810
|
return [h for (k, h) in legend.items()]
|
2083
1811
|
return []
|
2084
1812
|
|
1813
|
+
def render_areagroups(self, renderer):
|
1814
|
+
if not self.areagroup_list:
|
1815
|
+
return
|
1816
|
+
for area in self.areagroup_list:
|
1817
|
+
area.render(renderer,
|
1818
|
+
color="yellow",
|
1819
|
+
fill=False)
|
1820
|
+
return
|
1821
|
+
|
1822
|
+
def render_magnet_phi(self, renderer):
|
1823
|
+
magnets = [a for a in self.list_of_areas()]
|
1824
|
+
if not magnets:
|
1825
|
+
return
|
1826
|
+
arrow_len = [a.magnet_arrow_length() for a in magnets]
|
1827
|
+
length = max(arrow_len)
|
1828
|
+
|
1829
|
+
for area in magnets:
|
1830
|
+
area.render_magnet_phi(renderer, length)
|
1831
|
+
|
2085
1832
|
def get_points_in_iron(self):
|
2086
1833
|
points = []
|
2087
1834
|
for area in self.list_of_areas():
|
@@ -2114,6 +1861,10 @@ class Geometry(object):
|
|
2114
1861
|
atol = 3.0
|
2115
1862
|
|
2116
1863
|
logger.debug("*** Begin of get_machine() ***")
|
1864
|
+
|
1865
|
+
logger.debug(">> minmax: %s", mm)
|
1866
|
+
logger.debug(">> w=%s, h=%s", width, height)
|
1867
|
+
|
2117
1868
|
if np.isclose(height, width, self.rtol, self.atol):
|
2118
1869
|
radius = width/2
|
2119
1870
|
self.set_center([mm[1]-radius, mm[3]-radius])
|
@@ -2128,6 +1879,8 @@ class Geometry(object):
|
|
2128
1879
|
logger.info("check for quarter machine")
|
2129
1880
|
radius = width
|
2130
1881
|
self.set_center([mm[0], mm[2]])
|
1882
|
+
logger.debug("-- center = %s, radius min/max = %s/%s",
|
1883
|
+
self.center, self.min_radius, self.max_radius)
|
2131
1884
|
if self.check_hull(radius, mm[0], mm[2], self.rtol, atol):
|
2132
1885
|
logger.info(" - it is a quarter")
|
2133
1886
|
return Machine(self,
|
@@ -2303,7 +2056,7 @@ class Geometry(object):
|
|
2303
2056
|
m_min = min(m_min, m)
|
2304
2057
|
|
2305
2058
|
y = line_n([p[0]-center[0], p[1]], m_min)
|
2306
|
-
center[
|
2059
|
+
center = (center[0], y)
|
2307
2060
|
angle = alpha_line(center, p)
|
2308
2061
|
|
2309
2062
|
self.set_center([round(center[0], 8), round(center[1], 8)])
|
@@ -2406,8 +2159,20 @@ class Geometry(object):
|
|
2406
2159
|
return None
|
2407
2160
|
|
2408
2161
|
def get_center_arcs(self):
|
2162
|
+
logger.debug("begin of get_center_arcs")
|
2409
2163
|
center_list = []
|
2410
|
-
for e in self.elements(
|
2164
|
+
circles = [e for e in self.elements() if is_Circle(e)]
|
2165
|
+
logger.debug(" -- %s Circles", len(circles))
|
2166
|
+
|
2167
|
+
for e in circles:
|
2168
|
+
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2169
|
+
radius = round(e.radius, 1)
|
2170
|
+
center_list.append(([1], center, [radius]))
|
2171
|
+
|
2172
|
+
arcs = [e for e in self.elements() if is_Arc(e)]
|
2173
|
+
logger.debug(" -- %s Arcs", len(arcs))
|
2174
|
+
|
2175
|
+
for e in arcs:
|
2411
2176
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2412
2177
|
radius = round(e.radius, 1)
|
2413
2178
|
c = self.get_same_center(center_list, center, self.rtol, self.atol)
|
@@ -2429,6 +2194,8 @@ class Geometry(object):
|
|
2429
2194
|
c2 = arc_list[1]
|
2430
2195
|
if not c1[0] > c2[0]:
|
2431
2196
|
center = None
|
2197
|
+
|
2198
|
+
logger.debug("end of get_center_arcs: -> %s", center)
|
2432
2199
|
return center
|
2433
2200
|
|
2434
2201
|
def get_center_dim(self, mm):
|
@@ -2487,6 +2254,63 @@ class Geometry(object):
|
|
2487
2254
|
borders += 1
|
2488
2255
|
return (ok, borders)
|
2489
2256
|
|
2257
|
+
def check_airgap(self, startangle, endangle):
|
2258
|
+
logger.debug("begin check_airgap")
|
2259
|
+
area_id_list = [a.id for a in self.list_of_areas()]
|
2260
|
+
|
2261
|
+
def delete_id(id):
|
2262
|
+
try:
|
2263
|
+
i = area_id_list.index(id)
|
2264
|
+
except ValueError:
|
2265
|
+
return
|
2266
|
+
area_id_list[i] = 0
|
2267
|
+
# ---
|
2268
|
+
def append_area(alist, a):
|
2269
|
+
for my_a in alist:
|
2270
|
+
if my_a.is_in_touch_with_area(self, a):
|
2271
|
+
alist.append(a)
|
2272
|
+
delete_id(a.id)
|
2273
|
+
return True
|
2274
|
+
return False
|
2275
|
+
# ---
|
2276
|
+
for area in self.area_list:
|
2277
|
+
if not area.id in area_id_list:
|
2278
|
+
continue
|
2279
|
+
|
2280
|
+
for a in self.area_list:
|
2281
|
+
if area.id == a.id:
|
2282
|
+
continue
|
2283
|
+
if not a.id in area_id_list:
|
2284
|
+
continue
|
2285
|
+
|
2286
|
+
if area.the_area_is_inside_area(a):
|
2287
|
+
delete_id(a.id)
|
2288
|
+
|
2289
|
+
# collect remaining areas
|
2290
|
+
area_list = [a for a in self.area_list if a.id in area_id_list]
|
2291
|
+
group_list = {}
|
2292
|
+
for area in area_list:
|
2293
|
+
if not area.id in area_id_list:
|
2294
|
+
continue
|
2295
|
+
group_list[area.id] = [area]
|
2296
|
+
delete_id(area.id)
|
2297
|
+
for a in self.area_list:
|
2298
|
+
if area.id == a.id:
|
2299
|
+
continue
|
2300
|
+
if not a.id in area_id_list:
|
2301
|
+
continue
|
2302
|
+
if append_area(group_list[area.id], a):
|
2303
|
+
continue
|
2304
|
+
|
2305
|
+
area_list = [a for a in self.area_list if a.id in area_id_list]
|
2306
|
+
for area in area_list:
|
2307
|
+
group_list[area.id] = [area]
|
2308
|
+
|
2309
|
+
area_id_list = [int(x) for x in group_list.keys()]
|
2310
|
+
|
2311
|
+
logger.debug("end check_airgap: return %s", len(area_id_list) > 1)
|
2312
|
+
return len(area_id_list) > 1 # bad
|
2313
|
+
|
2490
2314
|
def is_border_line(self, center, startangle, endangle, e, atol):
|
2491
2315
|
if isinstance(e, Line):
|
2492
2316
|
if np.isclose(startangle, endangle):
|
@@ -2647,6 +2471,14 @@ class Geometry(object):
|
|
2647
2471
|
|
2648
2472
|
def create_auxiliary_lines(self, rightangle, leftangle):
|
2649
2473
|
logger.debug("begin of create_auxiliary_lines")
|
2474
|
+
timer = Timer(start_it=True)
|
2475
|
+
|
2476
|
+
# for future (next release)
|
2477
|
+
# area_list = self.list_of_areas()
|
2478
|
+
# builder = AreaBuilder(geom=self)
|
2479
|
+
# builder.create_area_groups(area_list)
|
2480
|
+
# self.areagroup_list = builder.area_list
|
2481
|
+
|
2650
2482
|
self.set_areas_inside_for_all_areas()
|
2651
2483
|
|
2652
2484
|
logger.debug("-> start create_auxiliary_lines")
|
@@ -2655,7 +2487,8 @@ class Geometry(object):
|
|
2655
2487
|
for area in self.list_of_areas():
|
2656
2488
|
if self.create_aux_lines(area, rightangle, leftangle):
|
2657
2489
|
done = True
|
2658
|
-
|
2490
|
+
t = timer.stop("-- auxiliary lines in %0.4f seconds --")
|
2491
|
+
self.journal.put('time_auxiliary_lines', t)
|
2659
2492
|
logger.debug("end of create_auxiliary_lines")
|
2660
2493
|
return done
|
2661
2494
|
|
@@ -2664,7 +2497,7 @@ class Geometry(object):
|
|
2664
2497
|
|
2665
2498
|
areas_inside = area.areas_inside.values()
|
2666
2499
|
if not areas_inside:
|
2667
|
-
logger.debug("end create_aux_lines() for %s (no areas inside)",
|
2500
|
+
logger.debug("end of create_aux_lines() for %s (no areas inside)",
|
2668
2501
|
area.get_id())
|
2669
2502
|
return False
|
2670
2503
|
|
@@ -2861,21 +2694,22 @@ class Geometry(object):
|
|
2861
2694
|
line = aux_line['line']
|
2862
2695
|
n1 = self.find_the_node(aux_line['p1'])
|
2863
2696
|
n2 = self.find_the_node(aux_line['p2'])
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2697
|
+
logger.debug("Line: n1=%s, n2=%s", n1, n2)
|
2698
|
+
|
2699
|
+
pts = self.split_and_get_intersect_points(line)
|
2700
|
+
if len(pts) != 2:
|
2701
|
+
logger.error("ERROR in create_aux_lines()")
|
2702
|
+
logger.debug("Points: %s", pts)
|
2703
|
+
logger.debug("Line: %s", line)
|
2704
|
+
|
2705
|
+
n1 = self.find_the_node(line.node1(ndec))
|
2706
|
+
n2 = self.find_the_node(line.node2(ndec))
|
2707
|
+
logger.debug("Line: n1=%s, n2=%s", n1, n2)
|
2872
2708
|
if n1 and n2:
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
self.rtol,
|
2878
|
-
self.atol)
|
2709
|
+
logger.debug("Create Line %s", aux_line['pattern'])
|
2710
|
+
self.add_element(line,
|
2711
|
+
rtol=self.rtol,
|
2712
|
+
atol=self.atol)
|
2879
2713
|
logger.debug("=== Create auxiliary line: %s", aux_line)
|
2880
2714
|
if aux_line['connect'] == 'child':
|
2881
2715
|
for a in areas_inside:
|
@@ -2889,7 +2723,7 @@ class Geometry(object):
|
|
2889
2723
|
logger.debug("end create_aux_lines() for %s (no iron)",
|
2890
2724
|
area.get_id())
|
2891
2725
|
return done
|
2892
|
-
|
2726
|
+
return done
|
2893
2727
|
# -----------------
|
2894
2728
|
def id_of_inside_area(p):
|
2895
2729
|
for a in areas_inside:
|
@@ -2925,7 +2759,10 @@ class Geometry(object):
|
|
2925
2759
|
# ----------
|
2926
2760
|
|
2927
2761
|
# Arcs as additional auxiliary connections thru iron
|
2762
|
+
logger.debug("Additional Lines in %s", area.identifier())
|
2928
2763
|
for a in area_to_parent_list:
|
2764
|
+
logger.debug("Area %s in Parent List", a.identifier())
|
2765
|
+
|
2929
2766
|
mid_dist = (a.min_dist + a.max_dist) / 2
|
2930
2767
|
mid_angle = (a.min_angle + a.max_angle) / 2
|
2931
2768
|
arc = Arc(Element(center=self.center,
|
@@ -2949,12 +2786,14 @@ class Geometry(object):
|
|
2949
2786
|
radius=mid_dist,
|
2950
2787
|
start_angle=start_angle*180/np.pi,
|
2951
2788
|
end_angle=end_angle*180/np.pi),
|
2952
|
-
color=aux_color,
|
2789
|
+
color='black', #aux_color,
|
2953
2790
|
linestyle=aux_linestyle)
|
2954
2791
|
arc.set_attribute('iron_sep')
|
2955
2792
|
self.split_and_get_intersect_points(arc)
|
2956
2793
|
n = self.find_nodes(pts[0], pts[1])
|
2957
|
-
self.
|
2794
|
+
self.add_or_join_edge(n[0], n[1], arc,
|
2795
|
+
rtol=self.rtol,
|
2796
|
+
atol=self.atol)
|
2958
2797
|
|
2959
2798
|
logger.debug("end create_aux_lines() for %s",
|
2960
2799
|
area.get_id())
|
@@ -3000,53 +2839,80 @@ class Geometry(object):
|
|
3000
2839
|
dict12['deleted'] = True
|
3001
2840
|
dict01['deleted'] = True
|
3002
2841
|
line = Line(Element(start=n0, end=n2))
|
3003
|
-
self.
|
2842
|
+
self.add_element(line,
|
2843
|
+
rtol=self.rtol,
|
2844
|
+
atol=self.atol)
|
3004
2845
|
return True
|
3005
2846
|
|
3006
|
-
def
|
2847
|
+
def search_tiny_elements(self, mindist):
|
2848
|
+
logger.debug("begin of search_tiny_elements(%s)", mindist)
|
3007
2849
|
if mindist == 0.0:
|
3008
|
-
return
|
2850
|
+
return []
|
3009
2851
|
|
3010
2852
|
edges = [edge for edge in self.g.edges(data=True)
|
3011
2853
|
if distance(edge[0], edge[1]) < mindist]
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
2854
|
+
|
2855
|
+
logger.debug("end of search_tiny_elements: %s tiny elements found",
|
2856
|
+
len(edges))
|
2857
|
+
return edges
|
2858
|
+
|
2859
|
+
def delete_tiny_elements(self, mindist):
|
2860
|
+
logger.debug("begin of delete_tiny_elements(%s)", mindist)
|
2861
|
+
edges = self.search_tiny_elements(mindist)
|
2862
|
+
if not edges:
|
2863
|
+
logger.debug("-- no tiny elements found")
|
2864
|
+
return
|
2865
|
+
|
3015
2866
|
deleted = 0
|
3016
2867
|
for edge in edges:
|
3017
|
-
|
2868
|
+
n1 = edge[0]
|
2869
|
+
n2 = edge[1]
|
2870
|
+
el = edge[2]['object']
|
2871
|
+
logger.debug("-- %s: %s <-> %s", el.classname(), n1, n2)
|
2872
|
+
logger.debug("Edge: %s", el.classname())
|
2873
|
+
|
2874
|
+
if n1 is n2:
|
2875
|
+
logger.debug("-- delete edge with equal nodes")
|
2876
|
+
self._remove_edge(n1, n2)
|
2877
|
+
deleted += 1
|
3018
2878
|
continue
|
3019
2879
|
|
3020
|
-
nbrs_n1 = [nbr for nbr in self.g.neighbors(
|
3021
|
-
if nbr
|
3022
|
-
nbrs_n2 = [nbr for nbr in self.g.neighbors(
|
3023
|
-
if nbr
|
2880
|
+
nbrs_n1 = [nbr for nbr in self.g.neighbors(n1)
|
2881
|
+
if not nodes_are_equal(nbr, n2)]
|
2882
|
+
nbrs_n2 = [nbr for nbr in self.g.neighbors(n2)
|
2883
|
+
if not nodes_are_equal(nbr, n1)]
|
2884
|
+
|
2885
|
+
if len(nbrs_n1) == 0 and len(nbrs_n2) == 0:
|
2886
|
+
# lonesome edge
|
2887
|
+
logger.debug("-- delete lonesome edge")
|
2888
|
+
self._remove_edge(n1, n2)
|
2889
|
+
deleted += 1
|
2890
|
+
continue
|
3024
2891
|
|
3025
2892
|
if len(nbrs_n1) == 1:
|
3026
|
-
if self._delete_a_tiny_element(edge[
|
3027
|
-
edge[2], nbrs_n1[0]):
|
2893
|
+
if self._delete_a_tiny_element(n2, n1, edge[2], nbrs_n1[0]):
|
3028
2894
|
deleted += 1
|
3029
2895
|
continue
|
3030
2896
|
|
3031
2897
|
if len(nbrs_n2) == 1:
|
3032
|
-
if self._delete_a_tiny_element(edge[
|
3033
|
-
edge[2], nbrs_n2[0]):
|
2898
|
+
if self._delete_a_tiny_element(n1, n2, edge[2], nbrs_n2[0]):
|
3034
2899
|
deleted += 1
|
3035
2900
|
continue
|
3036
2901
|
|
3037
2902
|
if deleted:
|
3038
|
-
logger.
|
2903
|
+
logger.debug("%s tiny elements deleted", deleted)
|
2904
|
+
logger.debug("end of delete_tiny_elements")
|
3039
2905
|
return
|
3040
2906
|
|
3041
2907
|
def check_shaft_area(self, shaft):
|
3042
2908
|
for a in self.list_of_areas():
|
3043
2909
|
if not shaft.is_identical(a):
|
3044
2910
|
if shaft.is_inside(a, self):
|
3045
|
-
shaft.
|
2911
|
+
shaft.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3046
2912
|
return
|
3047
2913
|
if shaft.is_touching(a):
|
3048
2914
|
if not a.is_iron():
|
3049
|
-
shaft.
|
2915
|
+
shaft.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3050
2916
|
return
|
3051
2917
|
|
3052
2918
|
def mark_connecting_edges(self, windings):
|
@@ -3060,18 +2926,19 @@ class Geometry(object):
|
|
3060
2926
|
for e in elist:
|
3061
2927
|
e.init_attributes('lightblue', 'no_fsl')
|
3062
2928
|
|
3063
|
-
def search_subregions(self):
|
2929
|
+
def search_subregions(self, startangle, endangle, single=False):
|
3064
2930
|
if self.is_stator():
|
3065
|
-
self.search_stator_subregions()
|
2931
|
+
self.search_stator_subregions(startangle, endangle, single=single)
|
3066
2932
|
elif self.is_rotor():
|
3067
|
-
self.search_rotor_subregions()
|
2933
|
+
self.search_rotor_subregions(startangle, endangle, single=single)
|
3068
2934
|
else:
|
3069
2935
|
logger.warning("no stator or rotor assigned")
|
3070
2936
|
self.search_unknown_subregions()
|
3071
2937
|
self.looking_for_corners()
|
3072
2938
|
|
3073
2939
|
def get_windings(self, type):
|
3074
|
-
windings = [a for a in self.list_of_areas()
|
2940
|
+
windings = [a for a in self.list_of_areas()
|
2941
|
+
if a.is_type(type)]
|
3075
2942
|
for w in windings:
|
3076
2943
|
inside = []
|
3077
2944
|
for a in self.list_of_areas():
|
@@ -3079,13 +2946,14 @@ class Geometry(object):
|
|
3079
2946
|
if w.is_inside(a, self):
|
3080
2947
|
inside.append(a)
|
3081
2948
|
if inside:
|
3082
|
-
w.set_type(
|
3083
|
-
return [a for a in self.list_of_areas()
|
2949
|
+
w.set_type(AREA.TYPE_AIR) # air
|
2950
|
+
return [a for a in self.list_of_areas()
|
2951
|
+
if a.is_type(type)]
|
3084
2952
|
|
3085
2953
|
def collect_windings(self):
|
3086
2954
|
logger.debug("begin of collect_windings")
|
3087
|
-
good_windings = self.get_windings(
|
3088
|
-
ugly_windings = self.get_windings(
|
2955
|
+
good_windings = self.get_windings(AREA.TYPE_WINDINGS)
|
2956
|
+
ugly_windings = self.get_windings(AREA.TYPE_WINDINGS_OR_AIR)
|
3089
2957
|
|
3090
2958
|
logger.debug("-- %s good and %s ugly windings",
|
3091
2959
|
len(good_windings),
|
@@ -3097,8 +2965,8 @@ class Geometry(object):
|
|
3097
2965
|
|
3098
2966
|
if not good_windings:
|
3099
2967
|
logger.debug("#2 end of collect_windings: %s windings", len(ugly_windings))
|
3100
|
-
[w.set_type(
|
3101
|
-
return [a for a in self.list_of_areas() if a.
|
2968
|
+
[w.set_type(AREA.TYPE_WINDINGS) for w in ugly_windings]
|
2969
|
+
return [a for a in self.list_of_areas() if a.is_type(AREA.TYPE_WINDINGS)]
|
3102
2970
|
|
3103
2971
|
# ggod and ugly windings available
|
3104
2972
|
found = True
|
@@ -3106,27 +2974,28 @@ class Geometry(object):
|
|
3106
2974
|
found = False
|
3107
2975
|
for a in ugly_windings:
|
3108
2976
|
if a.is_touching_areas(good_windings):
|
3109
|
-
a.set_type(
|
2977
|
+
a.set_type(AREA.TYPE_WINDINGS)
|
3110
2978
|
found = True
|
3111
2979
|
|
3112
|
-
good_windings = [a for a in self.list_of_areas()
|
3113
|
-
|
2980
|
+
good_windings = [a for a in self.list_of_areas()
|
2981
|
+
if a.is_type(AREA.TYPE_WINDINGS)]
|
2982
|
+
ugly_windings = [a for a in self.list_of_areas()
|
2983
|
+
if a.is_type(AREA.TYPE_WINDINGS_OR_AIR)]
|
3114
2984
|
|
3115
|
-
[w.set_type(
|
3116
|
-
good_windings = [a for a in self.list_of_areas()
|
2985
|
+
[w.set_type(AREA.TYPE_AIR) for w in ugly_windings]
|
2986
|
+
good_windings = [a for a in self.list_of_areas()
|
2987
|
+
if a.is_type(AREA.TYPE_WINDINGS)]
|
3117
2988
|
|
3118
|
-
logger.debug("return
|
2989
|
+
logger.debug("return bad and ugly windings as %s good windings", len(good_windings))
|
3119
2990
|
logger.debug("end of collect_windings")
|
3120
2991
|
return good_windings
|
3121
2992
|
|
3122
|
-
def search_stator_subregions(self,
|
2993
|
+
def search_stator_subregions(self,
|
2994
|
+
startangle,
|
2995
|
+
endangle,
|
2996
|
+
single=False):
|
3123
2997
|
logger.debug("Begin of search_stator_subregions")
|
3124
2998
|
|
3125
|
-
if place == 'in':
|
3126
|
-
self.is_inner = True
|
3127
|
-
elif place == 'out':
|
3128
|
-
self.is_inner = False
|
3129
|
-
|
3130
2999
|
if self.alfa == 0.0:
|
3131
3000
|
self.alfa = np.pi * 2.0
|
3132
3001
|
|
@@ -3141,18 +3010,20 @@ class Geometry(object):
|
|
3141
3010
|
self.max_radius)
|
3142
3011
|
|
3143
3012
|
windings = self.collect_windings()
|
3144
|
-
[a.set_type(
|
3013
|
+
[a.set_type(AREA.TYPE_AIR) for a in self.list_of_areas()
|
3014
|
+
if a.is_type(AREA.TYPE_WINDINGS_OR_AIR)]
|
3145
3015
|
windings_found = len(windings)
|
3146
3016
|
logger.debug("%d windings found", windings_found)
|
3017
|
+
self.has_windings = windings_found > 0
|
3147
3018
|
|
3148
3019
|
if windings_found > 1:
|
3149
3020
|
windings_surface = [[w.surface, w] for w in windings]
|
3150
3021
|
windings_surface.sort(reverse=True)
|
3151
|
-
max_size = windings_surface[0]
|
3152
|
-
for sz, w in windings_surface:
|
3022
|
+
max_size, max_w = windings_surface[0]
|
3023
|
+
for sz, w in windings_surface[1:]:
|
3153
3024
|
logger.debug("winding size = %s", sz)
|
3154
|
-
if sz / max_size < 0.
|
3155
|
-
w.set_type(
|
3025
|
+
if sz / max_size < 0.80:
|
3026
|
+
w.set_type(AREA.TYPE_AIR)
|
3156
3027
|
if sz / max_size < 0.2:
|
3157
3028
|
windings_found -= 1
|
3158
3029
|
windings = [a for a in self.list_of_areas()
|
@@ -3160,8 +3031,9 @@ class Geometry(object):
|
|
3160
3031
|
if windings_found > 2 and len(windings) == 1:
|
3161
3032
|
logger.info("no windings remaining")
|
3162
3033
|
# no windings
|
3163
|
-
[w.set_type(
|
3164
|
-
[a.set_type(
|
3034
|
+
[w.set_type(AREA.TYPE_AIR) for w in windings]
|
3035
|
+
[a.set_type(AREA.TYPE_IRON) for a in self.list_of_areas()
|
3036
|
+
if a.is_iron()]
|
3165
3037
|
windings = []
|
3166
3038
|
elif len(windings) < windings_found:
|
3167
3039
|
logger.info("%d windings remaining", len(windings))
|
@@ -3197,7 +3069,8 @@ class Geometry(object):
|
|
3197
3069
|
self.wdg_is_mirrored = False
|
3198
3070
|
|
3199
3071
|
# air or iron near windings and near airgap ?
|
3200
|
-
air_areas = [a for a in self.list_of_areas()
|
3072
|
+
air_areas = [a for a in self.list_of_areas()
|
3073
|
+
if a.is_type(AREA.TYPE_AIR_OR_IRON)]
|
3201
3074
|
for a in air_areas:
|
3202
3075
|
if a.around_windings(windings, self):
|
3203
3076
|
logger.debug("Area %s", a.identifier())
|
@@ -3211,7 +3084,7 @@ class Geometry(object):
|
|
3211
3084
|
if a.close_to_startangle:
|
3212
3085
|
if not wdg_close_to_startangle:
|
3213
3086
|
logger.debug("#0.1 ===> close to startangle")
|
3214
|
-
a.
|
3087
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3215
3088
|
continue
|
3216
3089
|
|
3217
3090
|
if a.close_to_endangle:
|
@@ -3219,10 +3092,10 @@ class Geometry(object):
|
|
3219
3092
|
logger.debug("#0.2 ===> close to endangle")
|
3220
3093
|
if(a.min_angle < wdg_min_angle and
|
3221
3094
|
a.close_to_ag):
|
3222
|
-
a.
|
3095
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3223
3096
|
continue
|
3224
3097
|
|
3225
|
-
a.
|
3098
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3226
3099
|
continue
|
3227
3100
|
|
3228
3101
|
if greater_equal(a.min_air_angle, wdg_min_angle):
|
@@ -3232,53 +3105,54 @@ class Geometry(object):
|
|
3232
3105
|
|
3233
3106
|
if a.close_to_endangle and self.is_mirrored():
|
3234
3107
|
logger.debug("#1 ===> endangle and mirrored <===")
|
3235
|
-
a.
|
3108
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3236
3109
|
elif less_equal(a.max_air_angle, wdg_max_angle):
|
3237
3110
|
logger.debug("#2 ===> %s <= %s <===",
|
3238
3111
|
a.max_air_angle,
|
3239
3112
|
wdg_max_angle)
|
3240
|
-
a.
|
3113
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3241
3114
|
else:
|
3242
3115
|
logger.debug("#3 ===> %s > %s <===",
|
3243
3116
|
a.max_air_angle,
|
3244
3117
|
wdg_max_angle)
|
3245
|
-
a.
|
3118
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3246
3119
|
else:
|
3247
3120
|
logger.debug("#4 ===> %s < %s <===",
|
3248
3121
|
a.min_air_angle,
|
3249
3122
|
wdg_min_angle)
|
3250
|
-
a.
|
3123
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3251
3124
|
else:
|
3252
3125
|
logger.debug("#5 not around windings")
|
3253
|
-
a.
|
3126
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3254
3127
|
|
3255
3128
|
# yoke or shaft ?
|
3256
|
-
iron_areas = [a for a in self.list_of_areas()
|
3129
|
+
iron_areas = [a for a in self.list_of_areas()
|
3130
|
+
if a.is_type(AREA.TYPE_YOKE)]
|
3257
3131
|
for a in iron_areas:
|
3258
3132
|
if a.around_windings(windings, self):
|
3259
3133
|
if less(a.min_dist, wdg_max_dist):
|
3260
3134
|
if less_equal(a.max_dist, wdg_max_dist):
|
3261
|
-
a.
|
3135
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3262
3136
|
else:
|
3263
3137
|
dist_low = wdg_max_dist - a.min_dist
|
3264
3138
|
dist_up = a.max_dist - wdg_max_dist
|
3265
3139
|
if dist_low > dist_up:
|
3266
|
-
a.
|
3140
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3267
3141
|
|
3268
|
-
shaft_areas = [a for a in self.list_of_areas()
|
3142
|
+
shaft_areas = [a for a in self.list_of_areas()
|
3143
|
+
if a.is_type(AREA.TYPE_SHAFT)]
|
3269
3144
|
if shaft_areas:
|
3270
3145
|
if len(shaft_areas) > 1:
|
3271
|
-
logger.
|
3146
|
+
logger.debug("More than one shaft in stator ?!?")
|
3272
3147
|
return
|
3273
3148
|
self.check_shaft_area(shaft_areas[0])
|
3149
|
+
logger.debug("End of search_stator_subregions")
|
3274
3150
|
|
3275
|
-
def search_rotor_subregions(self,
|
3276
|
-
|
3277
|
-
|
3278
|
-
|
3279
|
-
|
3280
|
-
elif place == 'out':
|
3281
|
-
self.is_inner = False
|
3151
|
+
def search_rotor_subregions(self,
|
3152
|
+
startangle,
|
3153
|
+
endangle,
|
3154
|
+
single=False):
|
3155
|
+
logger.debug("Begin of search_rotor_subregions")
|
3282
3156
|
|
3283
3157
|
if self.alfa == 0.0:
|
3284
3158
|
self.alfa = np.pi * 2.0
|
@@ -3290,20 +3164,65 @@ class Geometry(object):
|
|
3290
3164
|
self.alfa,
|
3291
3165
|
self.center,
|
3292
3166
|
self.min_radius,
|
3293
|
-
self.max_radius
|
3167
|
+
self.max_radius,
|
3168
|
+
startangle,
|
3169
|
+
endangle)
|
3294
3170
|
if t in types:
|
3295
3171
|
types[t] += 1
|
3296
3172
|
else:
|
3297
3173
|
types[t] = 1
|
3298
3174
|
|
3299
|
-
if
|
3175
|
+
if AREA.TYPE_SHAFT in types:
|
3300
3176
|
logger.debug("Shaft is available")
|
3301
3177
|
|
3302
|
-
if
|
3303
|
-
if types
|
3304
|
-
|
3178
|
+
if AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP in types: # magnet rectangle near ag
|
3179
|
+
if AREA.TYPE_MAGNET_RECT in types: # magnet rectangle
|
3180
|
+
mag_rectangles = [a for a in self.list_of_areas()
|
3181
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3182
|
+
for a in mag_rectangles:
|
3183
|
+
if self.is_inner:
|
3184
|
+
dist_1 = a.max_dist + 0.5
|
3185
|
+
dist_2 = self.max_radius + 5
|
3186
|
+
else:
|
3187
|
+
dist_1 = a_min_dist - 0.5
|
3188
|
+
dist_2 = self.min_radius - 5
|
3189
|
+
|
3190
|
+
mid_angle = a.get_mid_angle(self.center)
|
3191
|
+
p1 = point(self.center, dist_1, mid_angle)
|
3192
|
+
p2 = point(self.center, dist_2, mid_angle)
|
3193
|
+
line = Line(Element(start=p1, end=p2))
|
3194
|
+
logger.debug("magnet intersect line: %s to %s", p1, p2)
|
3195
|
+
pts = self.split_and_get_intersect_points(line,
|
3196
|
+
aktion=False,
|
3197
|
+
include_end=False)
|
3198
|
+
logger.debug("magnet intersect points: %s", pts)
|
3199
|
+
if not pts:
|
3200
|
+
a.set_type(AREA.TYPE_MAGNET_UNDEFINED)
|
3201
|
+
mag_rectangles = [a for a in self.list_of_areas()
|
3202
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3203
|
+
if mag_rectangles: # undo
|
3204
|
+
logger.debug("--- undo ---")
|
3205
|
+
[a.set_type(AREA.TYPE_MAGNET_RECT) for a in self.list_of_areas()
|
3206
|
+
if a.is_type(AREA.TYPE_MAGNET_UNDEFINED)]
|
3207
|
+
else:
|
3208
|
+
logger.debug("--- set type 3 ---")
|
3209
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3210
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP)]
|
3211
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3212
|
+
if a.is_type(AREA.TYPE_MAGNET_UNDEFINED)]
|
3213
|
+
types.pop(AREA.TYPE_MAGNET_RECT)
|
3214
|
+
else:
|
3215
|
+
# set magnet
|
3216
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3217
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP)]
|
3218
|
+
types[AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP] = 0
|
3219
|
+
|
3220
|
+
if AREA.TYPE_MAGNET_RECT in types: # magnet rectangle
|
3221
|
+
if types[AREA.TYPE_MAGNET_RECT] > 1:
|
3222
|
+
logger.debug("%s embedded magnets in rotor",
|
3223
|
+
types[AREA.TYPE_MAGNET_RECT])
|
3305
3224
|
emb_mag_areas = [a for a in self.list_of_areas()
|
3306
|
-
if a.
|
3225
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3307
3226
|
[a.set_surface(self.is_mirrored()) for a in emb_mag_areas]
|
3308
3227
|
max_surface = 0.0
|
3309
3228
|
max_phi = 0.0
|
@@ -3315,30 +3234,34 @@ class Geometry(object):
|
|
3315
3234
|
for a in emb_mag_areas:
|
3316
3235
|
if a.surface < max_surface * 0.20: # too small
|
3317
3236
|
logger.debug(
|
3318
|
-
"embedded magnet too small: convert to air"
|
3237
|
+
"embedded magnet %s too small: convert to air",
|
3238
|
+
a.identifier())
|
3319
3239
|
logger.debug("max surface : %s", max_surface)
|
3320
3240
|
logger.debug("area surface: %s", a.surface)
|
3321
3241
|
logger.debug("max phi : %s", max_phi)
|
3322
3242
|
logger.debug("area phi : %s", a.phi)
|
3323
3243
|
if not np.isclose(a.phi, max_phi):
|
3324
|
-
a.set_type(
|
3244
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3325
3245
|
|
3326
3246
|
# set iron
|
3327
|
-
[a.set_type(
|
3247
|
+
[a.set_type(AREA.TYPE_IRON) for a in self.list_of_areas()
|
3248
|
+
if a.is_type(AREA.TYPE_MAGNET_AIRGAP)]
|
3328
3249
|
|
3329
|
-
iron_mag_areas = [a for a in self.list_of_areas()
|
3330
|
-
|
3250
|
+
iron_mag_areas = [a for a in self.list_of_areas()
|
3251
|
+
if a.is_type(AREA.TYPE_MAGNET_OR_IRON)]
|
3252
|
+
air_mag_areas = [a for a in self.list_of_areas()
|
3253
|
+
if a.is_type(AREA.TYPE_MAGNET_OR_AIR)]
|
3331
3254
|
ag_areas = [a for a in self.list_of_areas() if a.close_to_ag]
|
3332
3255
|
if len(ag_areas) == 1:
|
3333
3256
|
if len(iron_mag_areas) == 1:
|
3334
|
-
[a.set_type(
|
3257
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in iron_mag_areas]
|
3335
3258
|
iron_mag_areas = []
|
3336
3259
|
if len(air_mag_areas) == 1:
|
3337
|
-
[a.set_type(
|
3260
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in air_mag_areas]
|
3338
3261
|
air_mag_areas = []
|
3339
3262
|
|
3340
|
-
[a.set_type(
|
3341
|
-
[a.set_type(
|
3263
|
+
[a.set_type(AREA.TYPE_IRON) for a in iron_mag_areas]
|
3264
|
+
[a.set_type(AREA.TYPE_AIR) for a in air_mag_areas]
|
3342
3265
|
|
3343
3266
|
if self.is_mirrored():
|
3344
3267
|
mid_alfa = round(self.alfa, 3)
|
@@ -3348,44 +3271,63 @@ class Geometry(object):
|
|
3348
3271
|
mag_areas = [[abs(round(a.phi, 3) - mid_alfa),
|
3349
3272
|
a.id,
|
3350
3273
|
a] for a in self.list_of_areas()
|
3351
|
-
if a.
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3355
|
-
phi_prev = mag_areas[0][0]
|
3356
|
-
phi_curr = phi_prev
|
3357
|
-
|
3358
|
-
for phi, id, a in mag_areas:
|
3359
|
-
# group around mid_alfa
|
3360
|
-
if phi > phi_prev + 0.33:
|
3361
|
-
phi_curr = phi
|
3362
|
-
|
3363
|
-
phi_prev = phi
|
3364
|
-
x = mag_phi.get(phi_curr, [0, []])
|
3365
|
-
x[0] += 1
|
3366
|
-
x[1].append(a)
|
3367
|
-
mag_phi[phi_curr] = x
|
3368
|
-
|
3369
|
-
phi_list = [[l[0], p, l[1]] for p, l in mag_phi.items()]
|
3370
|
-
phi_list.sort(reverse=True)
|
3371
|
-
if len(phi_list) > 1:
|
3372
|
-
c0 = phi_list[0][0]
|
3373
|
-
c1 = phi_list[1][0]
|
3374
|
-
first = 1
|
3375
|
-
if c0 == c1:
|
3376
|
-
first = 2
|
3377
|
-
|
3378
|
-
for c, phi, a_lst in phi_list[first:]:
|
3379
|
-
[a.set_type(0) for a in a_lst]
|
3380
|
-
|
3381
|
-
shaft_areas = [a for a in self.list_of_areas() if a.type == 10]
|
3274
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3275
|
+
|
3276
|
+
shaft_areas = [a for a in self.list_of_areas()
|
3277
|
+
if a.is_type(AREA.TYPE_SHAFT)]
|
3382
3278
|
if shaft_areas:
|
3383
3279
|
if len(shaft_areas) > 1:
|
3384
|
-
logger.
|
3280
|
+
logger.debug("More than one shaft in rotor ?!?")
|
3385
3281
|
return
|
3386
3282
|
self.check_shaft_area(shaft_areas[0])
|
3387
3283
|
|
3388
|
-
|
3284
|
+
magnets = [a for a in self.list_of_areas()
|
3285
|
+
if a.is_magnet()]
|
3286
|
+
self.has_magnets = len(magnets) > 0
|
3287
|
+
for m in magnets:
|
3288
|
+
m.phi = m.get_magnet_orientation()
|
3289
|
+
logger.debug("%s magnets found in rotor", len(magnets))
|
3290
|
+
|
3291
|
+
if not single:
|
3292
|
+
if not magnets:
|
3293
|
+
[a.set_type(AREA.TYPE_AIR) for a in self.list_of_areas()]
|
3294
|
+
self.search_stator_subregions(startangle, endangle, single=single)
|
3295
|
+
return
|
3296
|
+
|
3297
|
+
logger.debug("end of search_rotor_subregions")
|
3298
|
+
|
3299
|
+
def recalculate_magnet_orientation(self):
|
3300
|
+
logger.debug("begin of recalculate_magnet_orientation")
|
3301
|
+
magnet_areas = [a for a in self.list_of_areas()
|
3302
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3303
|
+
self.recalculate_magnet_group(magnet_areas)
|
3304
|
+
|
3305
|
+
magnet_areas = [a for a in self.list_of_areas()
|
3306
|
+
if a.is_type(AREA.TYPE_MAGNET_AIRGAP)]
|
3307
|
+
for a in magnet_areas:
|
3308
|
+
a.phi = a.get_magnet_orientation()
|
3309
|
+
logger.debug("end of recalculate_magnet_orientation")
|
3310
|
+
|
3311
|
+
def recalculate_magnet_group(self, areas):
|
3312
|
+
if not areas:
|
3313
|
+
return
|
3314
|
+
elements = []
|
3315
|
+
for a in areas:
|
3316
|
+
elements += a.elements()
|
3317
|
+
geom = Geometry(elements, center=self.center)
|
3318
|
+
builder = AreaBuilder(geom=geom)
|
3319
|
+
if builder.create_area_groups(areas):
|
3320
|
+
return # bad
|
3321
|
+
group_list = builder.area_list
|
3322
|
+
self.areagroup_list = group_list
|
3323
|
+
for group in group_list:
|
3324
|
+
if not group.is_magnet_rectangle():
|
3325
|
+
logger.debug("Warning: group is not a rectangle")
|
3326
|
+
group.set_type(AREA.TYPE_MAGNET_RECT)
|
3327
|
+
phi = group.get_magnet_orientation()
|
3328
|
+
for a in group.areas_of_group:
|
3329
|
+
logger.debug("Replace phi %s by %s", a.phi, phi)
|
3330
|
+
a.phi = phi
|
3389
3331
|
|
3390
3332
|
def search_unknown_subregions(self):
|
3391
3333
|
logger.debug("begin of search_unknown_subregions")
|
@@ -3401,22 +3343,31 @@ class Geometry(object):
|
|
3401
3343
|
else:
|
3402
3344
|
types[t] = 1
|
3403
3345
|
|
3404
|
-
if
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3346
|
+
if types.get(AREA.TYPE_MAGNET_RECT, 0) > 1:
|
3347
|
+
logger.debug("%s embedded magnets in rotor",
|
3348
|
+
types[AREA.TYPE_MAGNET_RECT])
|
3349
|
+
emb_mag_areas = [a for a in self.list_of_areas()
|
3350
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3351
|
+
[a.set_surface(self.is_mirrored()) for a in emb_mag_areas]
|
3352
|
+
max_surface = 0.0
|
3353
|
+
for a in emb_mag_areas:
|
3354
|
+
max_surface = max(max_surface, a.surface)
|
3413
3355
|
|
3414
|
-
|
3415
|
-
|
3416
|
-
|
3356
|
+
for a in emb_mag_areas:
|
3357
|
+
if a.surface < max_surface * 0.20: # too small
|
3358
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3417
3359
|
|
3418
3360
|
logger.debug("end of search_unknown_subregions")
|
3419
3361
|
|
3362
|
+
def magnets_in_the_middle(self, midangle):
|
3363
|
+
mag_areas = [a for a in self.list_of_areas()
|
3364
|
+
if a.is_magnet()]
|
3365
|
+
logger.debug("%s magnets in geom", len(mag_areas))
|
3366
|
+
for a in mag_areas:
|
3367
|
+
if a.max_angle > midangle and a.min_angle < midangle:
|
3368
|
+
return True
|
3369
|
+
return False
|
3370
|
+
|
3420
3371
|
def looking_for_corners(self):
|
3421
3372
|
if self.is_inner:
|
3422
3373
|
logger.debug("looking_for_corners: inner")
|
@@ -3434,14 +3385,14 @@ class Geometry(object):
|
|
3434
3385
|
|
3435
3386
|
def num_areas_of_type(self, type):
|
3436
3387
|
return len([area for area in self.list_of_areas()
|
3437
|
-
if area.type
|
3388
|
+
if area.is_type(type)])
|
3438
3389
|
|
3439
3390
|
def num_of_windings(self):
|
3440
|
-
return self.num_areas_of_type(
|
3391
|
+
return self.num_areas_of_type(AREA.TYPE_WINDINGS)
|
3441
3392
|
|
3442
3393
|
def area_close_to_endangle(self, type):
|
3443
3394
|
return len([area for area in self.list_of_areas()
|
3444
|
-
if area.type
|
3395
|
+
if area.is_type(type) and area.close_to_endangle])
|
3445
3396
|
|
3446
3397
|
def corners_dont_match(self):
|
3447
3398
|
if self.is_mirrored():
|
@@ -3460,7 +3411,7 @@ class Geometry(object):
|
|
3460
3411
|
return True
|
3461
3412
|
return False
|
3462
3413
|
|
3463
|
-
def
|
3414
|
+
def get_appendices(self):
|
3464
3415
|
c = 0
|
3465
3416
|
end_nodes = []
|
3466
3417
|
for n in self.g.nodes():
|
@@ -3473,154 +3424,202 @@ class Geometry(object):
|
|
3473
3424
|
|
3474
3425
|
if not is_Circle(el):
|
3475
3426
|
end_nodes.append((n, nbrs[0], el))
|
3427
|
+
return end_nodes
|
3428
|
+
|
3429
|
+
def connect_all_nodes(self,
|
3430
|
+
additional_nodes=[],
|
3431
|
+
rtol=1e-04, atol=1e-04,
|
3432
|
+
main=False):
|
3433
|
+
logger.debug("begin of connect_all_nodes")
|
3434
|
+
timer = Timer(start_it=True)
|
3435
|
+
nodes_list = self.get_nodes()
|
3436
|
+
c1 = 0
|
3437
|
+
c2 = 0
|
3438
|
+
additional_nodes_list = []
|
3439
|
+
for n in additional_nodes:
|
3440
|
+
if not n in nodes_list:
|
3441
|
+
additional_nodes_list.append(n)
|
3442
|
+
c1 += 1
|
3443
|
+
else:
|
3444
|
+
c2 += 1
|
3445
|
+
logger.debug("connect_all_nodes: %s added, %s already available", c1, c2)
|
3446
|
+
|
3447
|
+
corr = self.connect_nodes(nodes_list,
|
3448
|
+
rtol=rtol, atol=atol)
|
3449
|
+
if additional_nodes_list:
|
3450
|
+
corr += self.connect_nodes(additional_nodes_list,
|
3451
|
+
omit_single_element=True,
|
3452
|
+
rtol=rtol, atol=atol)
|
3453
|
+
t = timer.stop("-- {} connections in %0.4f seconds --".format(corr))
|
3454
|
+
if main:
|
3455
|
+
self.journal.put_nodes_connected(corr)
|
3456
|
+
self.journal.put('time_node_connections', t)
|
3457
|
+
logger.debug("==> %s nodes connected", corr)
|
3458
|
+
logger.debug("end of connect_all_nodes")
|
3459
|
+
return corr
|
3460
|
+
|
3461
|
+
def connect_nodes(self, nodes_list,
|
3462
|
+
rtol=1e-03, atol=1e-03,
|
3463
|
+
omit_single_element=False,
|
3464
|
+
ignore_end=False):
|
3465
|
+
logger.debug("begin of connect_nodes(rtol=%s, atol=%s)", rtol, atol)
|
3466
|
+
logger.debug("-- %s nodes exist", len(nodes_list))
|
3476
3467
|
|
3477
|
-
|
3478
|
-
|
3479
|
-
if self.node_connected(
|
3480
|
-
|
3468
|
+
count = 0
|
3469
|
+
for n in nodes_list:
|
3470
|
+
if self.node_connected(n,
|
3471
|
+
rtol=rtol, atol=atol,
|
3472
|
+
omit_single_element=omit_single_element,
|
3473
|
+
ignore_end=ignore_end):
|
3474
|
+
count += 1
|
3475
|
+
|
3476
|
+
logger.debug("end of connect_nodes => %s", count)
|
3477
|
+
return count
|
3478
|
+
|
3479
|
+
def connect_all_appendices(self, rtol=1e-04, atol=1e-04, main=False):
|
3480
|
+
logger.debug("begin of connect_all_appendices")
|
3481
|
+
timer = Timer(start_it=True)
|
3482
|
+
appendix_list = self.get_appendices()
|
3483
|
+
before = len(appendix_list)
|
3484
|
+
if main:
|
3485
|
+
self.journal.put_appendices(len(appendix_list))
|
3486
|
+
corr = self.connect_appendices(appendix_list, rtol=rtol, atol=atol)
|
3487
|
+
corr_total = corr
|
3488
|
+
|
3489
|
+
if corr < before:
|
3490
|
+
appendix_list = self.get_appendices()
|
3491
|
+
before = len(appendix_list)
|
3492
|
+
corr = self.connect_appendices(appendix_list, rtol=rtol, atol=atol)
|
3493
|
+
corr_total += corr
|
3494
|
+
t = timer.stop("-- {} connections in %0.4f seconds --".format(corr))
|
3495
|
+
if main:
|
3496
|
+
self.journal.put_appendices_connected(corr_total)
|
3497
|
+
self.journal.put('time_app_connections', t)
|
3498
|
+
|
3499
|
+
logger.debug("==> %s appendices connected", corr_total)
|
3500
|
+
logger.debug("end of connect_all_appendices")
|
3501
|
+
return corr_total
|
3502
|
+
|
3503
|
+
def connect_appendices(self, appendix_list, rtol=1e-03, atol=1e-03, ignore_end=False):
|
3504
|
+
logger.debug("begin of connect_appendices(rtol=%s, atol=%s)", rtol, atol)
|
3505
|
+
logger.debug("-- %s appendices exist", len(appendix_list))
|
3506
|
+
self.fixed_appendices = []
|
3507
|
+
|
3508
|
+
count = 0
|
3509
|
+
for n0, n1, el in appendix_list:
|
3510
|
+
logger.debug("Appendix Node at %s", n0)
|
3511
|
+
if n0 in self.fixed_appendices:
|
3512
|
+
logger.debug(" - Node already fixed")
|
3481
3513
|
else:
|
3482
|
-
|
3483
|
-
|
3484
|
-
|
3485
|
-
try:
|
3486
|
-
self._remove_edge(n0, n1)
|
3487
|
-
self.add_edge(nn, n1, el)
|
3488
|
-
except Exception:
|
3489
|
-
logger.debug("delete of %s - %s failed", n0, n)
|
3490
|
-
logger.debug("Element %s", el)
|
3491
|
-
return c
|
3514
|
+
count += self.connect_appendix(n0, n1, el,
|
3515
|
+
rtol=rtol, atol=atol,
|
3516
|
+
ignore_end=ignore_end)
|
3492
3517
|
|
3493
|
-
|
3494
|
-
c = 0
|
3495
|
-
end_nodes = []
|
3496
|
-
for n in self.g.nodes():
|
3497
|
-
nbrs = [nbr for nbr in self.g.neighbors(n)]
|
3498
|
-
if len(nbrs) == 1:
|
3499
|
-
end_nodes.append((n, nbrs[0]))
|
3518
|
+
self.fixed_appendices = []
|
3500
3519
|
|
3501
|
-
|
3502
|
-
|
3503
|
-
c += self.remove_appendix(n0, n1)
|
3504
|
-
return c
|
3520
|
+
logger.debug("end of connect_appendices => %s", count)
|
3521
|
+
return count
|
3505
3522
|
|
3506
|
-
def
|
3507
|
-
logger.debug("begin of
|
3508
|
-
c = 1
|
3509
|
-
corr = 0
|
3510
|
-
while c > 0:
|
3511
|
-
c = self.search_overlapping_elements()
|
3512
|
-
corr += c
|
3513
|
-
logger.debug("==> %s corrections performed", corr)
|
3514
|
-
logger.debug("end of search_all_overlapping_elements")
|
3515
|
-
|
3516
|
-
def search_all_appendices(self):
|
3517
|
-
logger.debug("begin of search_all_appendices")
|
3518
|
-
corr = self.search_appendices()
|
3519
|
-
logger.debug("==> %s appendices connected", corr)
|
3520
|
-
logger.debug("end of search_all_appendices")
|
3523
|
+
def connect_appendix(self, n0, n1, el, rtol=1e-03, atol=1e-03, ignore_end=False):
|
3524
|
+
logger.debug("begin of connect_appendix(%s, rtol=%s, atol=%s)", n0, rtol, atol)
|
3521
3525
|
|
3522
|
-
|
3523
|
-
|
3524
|
-
|
3525
|
-
|
3526
|
-
|
3526
|
+
if points_are_close(n0, n1, rtol=1e-04, atol=1e-04):
|
3527
|
+
# a very tiny appendix
|
3528
|
+
d = distance(n0, n1)
|
3529
|
+
if less(d, 0.001):
|
3530
|
+
logger.debug("-- WARNING: a very tiny appendix of length %s", d)
|
3531
|
+
nbr_list = [nbr for nbr in self.g.neighbors(n1)
|
3532
|
+
if not nodes_are_equal(nbr, n0)]
|
3527
3533
|
|
3528
|
-
|
3529
|
-
|
3530
|
-
|
3534
|
+
if len(nbr_list) == 0:
|
3535
|
+
logger.debug("end of connect_appendix: => lonesome appendix -> no action")
|
3536
|
+
return 0
|
3531
3537
|
|
3532
|
-
|
3533
|
-
|
3534
|
-
|
3535
|
-
continue
|
3536
|
-
logger.debug(" Node %s has %s neighbors", n, len(nbrs))
|
3537
|
-
edges = []
|
3538
|
-
for nbr in nbrs:
|
3539
|
-
e_dict = self.g.get_edge_data(n, nbr)
|
3540
|
-
if not e_dict:
|
3541
|
-
break
|
3542
|
-
e = e_dict.get('object', None)
|
3543
|
-
if not e:
|
3544
|
-
break
|
3545
|
-
edges.append([nbr, e])
|
3538
|
+
logger.debug(" remove it")
|
3539
|
+
self._remove_edge(n0, n1)
|
3540
|
+
return 1
|
3546
3541
|
|
3547
|
-
|
3548
|
-
|
3542
|
+
if self.node_connected(n0, rtol=rtol, atol=atol, ignore_end=ignore_end):
|
3543
|
+
logger.debug("end of connect_appendix: %s CONNECTED", n0)
|
3544
|
+
return 1
|
3549
3545
|
|
3550
|
-
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3554
|
-
n1 = edges[i][0]
|
3555
|
-
over_edges = [[e1.length(), n1]]
|
3556
|
-
# list entry [<length of edge>, <end node of edge>]
|
3557
|
-
for j in range(i+1, len(edges)):
|
3558
|
-
e2 = edges[j][1]
|
3559
|
-
if e2 is None:
|
3560
|
-
continue
|
3561
|
-
n2 = edges[j][0]
|
3562
|
-
if e1.overlapping_shapes(n, e2):
|
3563
|
-
over_edges.append([e2.length(), n2])
|
3564
|
-
edges[j][1] = None
|
3565
|
-
|
3566
|
-
if len(over_edges) > 1:
|
3567
|
-
if self.correct_overlapping(n, e1, over_edges):
|
3568
|
-
count += 1
|
3569
|
-
logger.debug("end of search_overlapping_elements(correct=%s)", count)
|
3570
|
-
return count
|
3546
|
+
nn = self.find_other_node(n0)
|
3547
|
+
if not nn:
|
3548
|
+
logger.debug("end of connect_appendix: => No node found nearby")
|
3549
|
+
return 0
|
3571
3550
|
|
3572
|
-
|
3573
|
-
|
3574
|
-
|
3575
|
-
|
3576
|
-
|
3577
|
-
self.
|
3578
|
-
|
3579
|
-
|
3551
|
+
logger.debug("Node %s is near %s", n0, nn)
|
3552
|
+
logger.debug(" -- appendix %s from %s to %s", el.classname(), n0, n1)
|
3553
|
+
try:
|
3554
|
+
logger.debug("remove edge of %s from %s to %s",
|
3555
|
+
el.classname(), el.p1, el.p2)
|
3556
|
+
self._remove_edge(n0, n1)
|
3557
|
+
except Exception:
|
3558
|
+
f = Path(__file__)
|
3559
|
+
msg = "{} #{}: delete of {} - {} failed".format(
|
3560
|
+
f.name, lineno(),
|
3561
|
+
n0, n1)
|
3562
|
+
self.journal.put_warning(msg)
|
3563
|
+
logger.warning("WARNING: %s", msg)
|
3564
|
+
logger.debug("-- Element %s", el)
|
3565
|
+
|
3566
|
+
self.add_or_join_edge(nn, n1, el,
|
3567
|
+
rtol=rtol,
|
3568
|
+
atol=atol)
|
3569
|
+
self.fixed_appendices.append(nn)
|
3570
|
+
logger.debug("end of connect_appendix: connected")
|
3571
|
+
return 1
|
3580
3572
|
|
3581
|
-
def
|
3582
|
-
|
3583
|
-
|
3584
|
-
|
3573
|
+
def delete_appendices(self, appendix_list):
|
3574
|
+
c = 0
|
3575
|
+
for n0, n1, e in appendix_list:
|
3576
|
+
logger.debug("Deadend Node at %s", n0)
|
3577
|
+
c += self.remove_appendix(n0, n1)
|
3578
|
+
return c
|
3585
3579
|
|
3586
|
-
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3590
|
-
|
3591
|
-
|
3592
|
-
|
3580
|
+
def delete_all_appendices(self):
|
3581
|
+
logger.debug("begin of delete_all_appendices")
|
3582
|
+
appendix_list = self.get_appendices()
|
3583
|
+
app = len(appendix_list)
|
3584
|
+
if not app:
|
3585
|
+
logger.debug("end of delete_all_appendices: no appendices")
|
3586
|
+
return
|
3587
|
+
|
3588
|
+
corr = self.delete_appendices(appendix_list)
|
3589
|
+
self.journal.put_appendices_deleted(corr)
|
3593
3590
|
|
3594
|
-
logger.debug("
|
3595
|
-
logger.debug("end of
|
3591
|
+
logger.debug("==> %s appendices removed", corr)
|
3592
|
+
logger.debug("end of delete_all_appendices")
|
3596
3593
|
|
3597
|
-
def connect_arc_or_line(self, n, el, n1, n2,
|
3598
|
-
elements = el.split([n], rtol=
|
3594
|
+
def connect_arc_or_line(self, n, el, n1, n2, rtol=1e-03, atol=1e-03, mdec=0):
|
3595
|
+
elements = el.split([n], rtol=rtol, atol=atol, mdec=mdec)
|
3599
3596
|
if len(elements) != 2:
|
3600
|
-
logger.
|
3601
|
-
logger.
|
3597
|
+
logger.warning("Not 2 Elements")
|
3598
|
+
logger.warning("split(rtol=%s, atol=%s, mdec=%s)", rtol, atol, mdec)
|
3599
|
+
logger.warning("Node {} in Element {}".format(n, el))
|
3602
3600
|
for e in elements:
|
3603
3601
|
logger.info(e)
|
3604
3602
|
assert(len(elements) == 2)
|
3605
3603
|
|
3606
3604
|
logger.debug("HIT! Node %s is in %s", n, el)
|
3607
|
-
logger.debug(" => remove
|
3605
|
+
logger.debug(" => remove %s", el)
|
3606
|
+
self.fixed_appendices.append(n1)
|
3607
|
+
self.fixed_appendices.append(n2)
|
3608
3608
|
self._remove_edge(n1, n2)
|
3609
3609
|
|
3610
3610
|
for element in elements:
|
3611
3611
|
logger.debug("Split: %s", element)
|
3612
3612
|
|
3613
|
-
rtol = tol
|
3614
|
-
atol = tol
|
3615
|
-
|
3616
3613
|
for element in elements:
|
3617
3614
|
n1_inside = element.is_point_inside(n1,
|
3618
3615
|
rtol=rtol,
|
3619
3616
|
atol=atol,
|
3617
|
+
mdec=mdec,
|
3620
3618
|
include_end=True)
|
3621
3619
|
n2_inside = element.is_point_inside(n2,
|
3622
3620
|
rtol=rtol,
|
3623
3621
|
atol=atol,
|
3622
|
+
mdec=mdec,
|
3624
3623
|
include_end=True)
|
3625
3624
|
if n1_inside and n2_inside:
|
3626
3625
|
logger.error("FATAL: both inside %s", element)
|
@@ -3629,37 +3628,63 @@ class Geometry(object):
|
|
3629
3628
|
else:
|
3630
3629
|
if n1_inside:
|
3631
3630
|
logger.debug(" <= #1 add from %s to %s", n1, n)
|
3632
|
-
self.
|
3631
|
+
self.add_element(element,
|
3632
|
+
rtol=self.rtol,
|
3633
|
+
atol=self.atol)
|
3633
3634
|
else:
|
3634
3635
|
logger.debug(" <= #2 add from %s to %s", n2, n)
|
3635
|
-
self.
|
3636
|
+
self.add_element(element,
|
3637
|
+
rtol=self.rtol,
|
3638
|
+
atol=self.atol)
|
3636
3639
|
|
3637
|
-
def connect_circle(self, n, el, n1, n2,
|
3638
|
-
elements = el.split([n], rtol=
|
3640
|
+
def connect_circle(self, n, el, n1, n2, rtol=1e-03, atol=1e-03):
|
3641
|
+
elements = el.split([n], rtol=rtol, atol=atol)
|
3639
3642
|
assert(len(elements) == 3)
|
3640
3643
|
|
3641
|
-
logger.debug("Node %s is in %s", n, el)
|
3642
|
-
logger.debug(" => remove from %s to %s", n1, n2)
|
3644
|
+
logger.debug("connect_circle: Node %s is in %s", n, el)
|
3645
|
+
logger.debug(" => remove %s from %s to %s", el.classname(), n1, n2)
|
3646
|
+
e = self.get_edge_element(n1, n2)
|
3647
|
+
if not e:
|
3648
|
+
logger.error("Element from %s to %s not found", n1, n2)
|
3649
|
+
else:
|
3650
|
+
logger.debug("Element to Remove: %s", e)
|
3643
3651
|
self._remove_edge(n1, n2)
|
3652
|
+
|
3644
3653
|
for element in elements:
|
3645
|
-
|
3646
|
-
|
3654
|
+
self.add_element(element,
|
3655
|
+
rtol=self.rtol,
|
3656
|
+
atol=self.atol)
|
3657
|
+
|
3658
|
+
def node_connected(self, n,
|
3659
|
+
rtol=1e-03, atol=1e-03,
|
3660
|
+
omit_single_element=False,
|
3661
|
+
ignore_end=False):
|
3662
|
+
mdec = 2
|
3663
|
+
count = 0
|
3664
|
+
el_list = []
|
3665
|
+
for n1, n2, el in self.elements_and_nodes(Shape):
|
3666
|
+
if not el.is_near(n):
|
3667
|
+
#logger.debug("Node %s is NOT near this edge", n)
|
3668
|
+
continue
|
3669
|
+
elif el.is_point_inside(n,
|
3670
|
+
rtol=rtol,
|
3671
|
+
atol=atol,
|
3672
|
+
mdec=mdec,
|
3673
|
+
include_end=False,
|
3674
|
+
ignore_end=ignore_end):
|
3675
|
+
logger.debug("Node %s is inside of an edge", n)
|
3676
|
+
el_list.append((n1, n2, el))
|
3647
3677
|
|
3648
|
-
|
3649
|
-
|
3650
|
-
|
3651
|
-
|
3652
|
-
if el:
|
3653
|
-
|
3654
|
-
|
3655
|
-
|
3656
|
-
|
3657
|
-
|
3658
|
-
self.connect_circle(n, el, e[0], e[1], tol=tol)
|
3659
|
-
else:
|
3660
|
-
self.connect_arc_or_line(n, el, e[0], e[1], tol=tol)
|
3661
|
-
return True
|
3662
|
-
return False
|
3678
|
+
if omit_single_element and len(el_list) < 2:
|
3679
|
+
return 0
|
3680
|
+
|
3681
|
+
for n1, n2, el in el_list:
|
3682
|
+
if is_Circle(el):
|
3683
|
+
self.connect_circle(n, el, n1, n2, rtol=rtol, atol=atol)
|
3684
|
+
else:
|
3685
|
+
self.connect_arc_or_line(n, el, n1, n2, rtol=rtol, atol=atol, mdec=mdec)
|
3686
|
+
count += 1
|
3687
|
+
return count
|
3663
3688
|
|
3664
3689
|
def remove_appendix(self, n1, n2, incr_text=''):
|
3665
3690
|
e_dict = self.g.get_edge_data(n1, n2)
|
@@ -3677,12 +3702,21 @@ class Geometry(object):
|
|
3677
3702
|
logger.debug("%s remove_appendix(%s, %s)", incr_text, n1, n2)
|
3678
3703
|
self._remove_edge(n1, n2)
|
3679
3704
|
c = 1
|
3680
|
-
|
3705
|
+
try:
|
3706
|
+
nbrs = [nbr for nbr in self.g.neighbors(n2)]
|
3707
|
+
except nx.NetworkXError:
|
3708
|
+
logger.debug("Node %s already deleted", n2)
|
3709
|
+
nbrs = []
|
3710
|
+
|
3681
3711
|
if len(nbrs) == 1:
|
3682
3712
|
c += self.remove_appendix(n2, nbrs[0], incr_text + '.')
|
3683
3713
|
return c
|
3684
3714
|
|
3685
|
-
def
|
3715
|
+
def adjust_all_points(self):
|
3716
|
+
for e in self.elements():
|
3717
|
+
e.adjust_points()
|
3718
|
+
|
3719
|
+
def split_and_get_intersect_points(self, el, aktion=True, include_end=True):
|
3686
3720
|
logger.debug("begin of split_and_get_intersect_points")
|
3687
3721
|
rtol = 1e-03
|
3688
3722
|
atol = 1e-03
|
@@ -3691,12 +3725,15 @@ class Geometry(object):
|
|
3691
3725
|
pts = e.intersect_shape(el,
|
3692
3726
|
rtol=rtol,
|
3693
3727
|
atol=atol,
|
3694
|
-
include_end=
|
3728
|
+
include_end=include_end)
|
3695
3729
|
if pts:
|
3730
|
+
logger.debug("Split %s", e)
|
3731
|
+
[logger.debug("-- intersect point %s", p) for p in pts]
|
3696
3732
|
pts_inside = []
|
3697
3733
|
pts_real = []
|
3698
3734
|
for p in pts:
|
3699
|
-
|
3735
|
+
incl_end = is_Circle(e)
|
3736
|
+
if not e.is_point_inside(p, rtol, atol, include_end=incl_end):
|
3700
3737
|
# get the real point
|
3701
3738
|
n = self.find_the_node(p)
|
3702
3739
|
if n:
|
@@ -3723,7 +3760,9 @@ class Geometry(object):
|
|
3723
3760
|
logger.debug(
|
3724
3761
|
"=== OMIT ELEMENT WITH SAME NODES ===")
|
3725
3762
|
else:
|
3726
|
-
self.
|
3763
|
+
self.add_or_join_edge(n[0], n[1], e,
|
3764
|
+
rtol=rtol,
|
3765
|
+
atol=atol)
|
3727
3766
|
points += pts_real
|
3728
3767
|
|
3729
3768
|
logger.debug("end of split_and_get_intersect_points")
|
@@ -3737,6 +3776,30 @@ class Geometry(object):
|
|
3737
3776
|
return True
|
3738
3777
|
return False
|
3739
3778
|
|
3779
|
+
def _line_inside_magnets(self, p1, p2):
|
3780
|
+
for area in self.list_of_areas():
|
3781
|
+
if area.is_magnet():
|
3782
|
+
if area.is_point_inside(p1):
|
3783
|
+
if area.is_point_inside(p2):
|
3784
|
+
return True
|
3785
|
+
return False
|
3786
|
+
|
3787
|
+
def _line_inside_air(self, p1, p2):
|
3788
|
+
for area in self.list_of_areas():
|
3789
|
+
if area.is_air():
|
3790
|
+
if area.is_point_inside(p1):
|
3791
|
+
if area.is_point_inside(p2):
|
3792
|
+
return True
|
3793
|
+
return False
|
3794
|
+
|
3795
|
+
def _line_inside_not_iron(self, p1, p2):
|
3796
|
+
for area in self.list_of_areas():
|
3797
|
+
if area.is_shaft() or area.is_air() or area.is_magnet():
|
3798
|
+
if area.is_point_inside(p1):
|
3799
|
+
if area.is_point_inside(p2):
|
3800
|
+
return True
|
3801
|
+
return False
|
3802
|
+
|
3740
3803
|
def inside_area_list(self, p):
|
3741
3804
|
for area in self.list_of_areas():
|
3742
3805
|
if area.is_point_inside(p):
|
@@ -3749,7 +3812,7 @@ class Geometry(object):
|
|
3749
3812
|
d = distance(self.center, p)
|
3750
3813
|
logger.debug("-- p = %s, dist = %s", p, d)
|
3751
3814
|
for a in self.inside_area_list(p):
|
3752
|
-
logger.debug("-- Area type = %s", a.
|
3815
|
+
logger.debug("-- Area type = %s", a.legend())
|
3753
3816
|
logger.debug(" min=%s, max= %s", a.min_dist, a.max_dist)
|
3754
3817
|
logger.debug(" close to start = %s", a.close_to_startangle)
|
3755
3818
|
logger.debug(" close to end = %s", a.close_to_endangle)
|
@@ -3775,17 +3838,47 @@ class Geometry(object):
|
|
3775
3838
|
p1 = p2
|
3776
3839
|
continue
|
3777
3840
|
|
3778
|
-
n = self.find_nodes(p1, p2)
|
3779
3841
|
line = Line(Element(start=p1, end=p2),
|
3780
3842
|
color='darkred',
|
3781
3843
|
linestyle='dotted')
|
3782
|
-
self.
|
3783
|
-
|
3844
|
+
self.add_element(line,
|
3845
|
+
rtol=self.rtol,
|
3846
|
+
atol=self.atol)
|
3847
|
+
logger.debug("add line(%s)", line)
|
3784
3848
|
created = True
|
3785
3849
|
p1 = p2
|
3786
3850
|
|
3787
3851
|
return created
|
3788
3852
|
|
3853
|
+
def create_lines_outside_magnets(self, points):
|
3854
|
+
logger.debug("begin of create_lines_outside_magnets")
|
3855
|
+
if not points:
|
3856
|
+
return False
|
3857
|
+
created = False
|
3858
|
+
|
3859
|
+
p1 = points[0]
|
3860
|
+
for p2 in points[1:]:
|
3861
|
+
logger.debug("try from %s to %s", p1, p2)
|
3862
|
+
if not points_are_close(p1, p2):
|
3863
|
+
logger.debug("Line from %s to %s", p1, p2)
|
3864
|
+
if self._line_inside_not_iron(p1, p2):
|
3865
|
+
logger.debug("- not in iron (%s, %s)", p1, p2)
|
3866
|
+
p1 = p2
|
3867
|
+
continue
|
3868
|
+
|
3869
|
+
line = Line(Element(start=p1, end=p2),
|
3870
|
+
color='darkred',
|
3871
|
+
linestyle='dotted')
|
3872
|
+
line.set_attribute('iron_sep')
|
3873
|
+
self.add_element(line,
|
3874
|
+
rtol=self.rtol,
|
3875
|
+
atol=self.atol)
|
3876
|
+
logger.debug("add line(%s)", line)
|
3877
|
+
created = True
|
3878
|
+
p1 = p2
|
3879
|
+
logger.debug("end of create_lines_outside_magnets")
|
3880
|
+
return created
|
3881
|
+
|
3789
3882
|
def has_areas_touching_both_sides(self):
|
3790
3883
|
for a in self.area_list:
|
3791
3884
|
if a.is_touching_both_sides():
|
@@ -3842,9 +3935,146 @@ class Geometry(object):
|
|
3842
3935
|
logger.debug("end of get_inner_airgap_line #%s", len(nodes))
|
3843
3936
|
return nodes, elements
|
3844
3937
|
|
3845
|
-
def
|
3938
|
+
def create_inner_corner_areas(self, startangle, endangle):
|
3846
3939
|
self.set_edge_attributes()
|
3847
|
-
|
3940
|
+
|
3941
|
+
builder = AreaBuilder(geom=self)
|
3942
|
+
builder.create_inner_corner_auxiliary_areas(startangle, endangle)
|
3943
|
+
|
3944
|
+
def repair_border_line(self, nodes):
|
3945
|
+
logger.debug("begin repair_border_line")
|
3946
|
+
for d, n, ok in nodes:
|
3947
|
+
logger.debug(" node=%s, ok=%s", n, ok)
|
3948
|
+
|
3949
|
+
d1, n1, ok1 = nodes[0]
|
3950
|
+
if not ok1: # fatal => ignore
|
3951
|
+
logger.debug("end repair_border_line: missing point %s", n1)
|
3952
|
+
return False
|
3953
|
+
d1, n1, ok1 = nodes[-1]
|
3954
|
+
if not ok1: # fatal => ignore
|
3955
|
+
logger.debug("end repair_border_line: missing point %s", n1)
|
3956
|
+
return False
|
3957
|
+
|
3958
|
+
remove_n1 = None
|
3959
|
+
for d2, n2, ok2 in nodes[1:]:
|
3960
|
+
if ok1 and not ok2:
|
3961
|
+
remove_n1 = n1
|
3962
|
+
if ok2 and remove_n1:
|
3963
|
+
try:
|
3964
|
+
self._remove_edge(remove_n1, n2)
|
3965
|
+
logger.debug("Remove Line %s -- %s", remove_n1, n2)
|
3966
|
+
except nx.NetworkXError:
|
3967
|
+
logger.debug("Warning: Remove Line %s -- %s failed", remove_n1, n2)
|
3968
|
+
logger.debug("end repair_border_line: failed")
|
3969
|
+
return False
|
3970
|
+
remove_n1 = None
|
3971
|
+
n1 = n2
|
3972
|
+
ok1 = ok2
|
3973
|
+
|
3974
|
+
d1, n1, ok1 = nodes[0]
|
3975
|
+
for d2, n2, ok2 in nodes[1:]:
|
3976
|
+
if not ok2: # new node
|
3977
|
+
self.add_line(n1, n2)
|
3978
|
+
logger.debug("Add Line %s -- %s", n1, n2)
|
3979
|
+
elif not ok1:
|
3980
|
+
self.add_line(n1, n2)
|
3981
|
+
logger.debug("Add Line %s -- %s", n1, n2)
|
3982
|
+
n1 = n2
|
3983
|
+
ok1 = ok2
|
3984
|
+
logger.debug("end repair_border_line")
|
3985
|
+
return True
|
3986
|
+
|
3987
|
+
def create_boundery_nodes(self,
|
3988
|
+
center,
|
3989
|
+
startangle,
|
3990
|
+
endangle,
|
3991
|
+
rtol=None, atol=None):
|
3992
|
+
if not rtol:
|
3993
|
+
rtol = 1e-4
|
3994
|
+
if not atol:
|
3995
|
+
atol = 1e-3
|
3996
|
+
|
3997
|
+
start_nodes = [n for n in self.angle_nodes(center, startangle, rtol, atol)]
|
3998
|
+
end_nodes = [n for n in self.angle_nodes(center, endangle, rtol, atol)]
|
3999
|
+
alpha = alpha_angle(startangle, endangle)
|
4000
|
+
|
4001
|
+
logger.debug("begin of create_boundery_nodes")
|
4002
|
+
start_rot_nodes = self.rotate_nodes(alpha, start_nodes)
|
4003
|
+
end_rot_nodes = self.rotate_nodes(-alpha, end_nodes)
|
4004
|
+
|
4005
|
+
def miss_nodelist(src_nodelist, dest_nodelist):
|
4006
|
+
nlist = []
|
4007
|
+
for src_n in src_nodelist:
|
4008
|
+
ok = False
|
4009
|
+
for dest_n in dest_nodelist:
|
4010
|
+
if points_are_close(src_n, dest_n, rtol=rtol, atol=atol):
|
4011
|
+
ok = True
|
4012
|
+
break
|
4013
|
+
if not ok:
|
4014
|
+
nlist.append(src_n)
|
4015
|
+
return nlist
|
4016
|
+
|
4017
|
+
logger.debug("Begin with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
|
4018
|
+
|
4019
|
+
missing_end_nodes = miss_nodelist(start_rot_nodes, end_nodes)
|
4020
|
+
missing_start_nodes = miss_nodelist(end_rot_nodes, start_nodes)
|
4021
|
+
|
4022
|
+
if missing_start_nodes:
|
4023
|
+
logger.debug("%s missing start nodes", len(missing_start_nodes))
|
4024
|
+
start_nodes = [(distance(center, n), n, True) for n in start_nodes]
|
4025
|
+
for n in missing_start_nodes:
|
4026
|
+
start_nodes.append((distance(center, n), n, False))
|
4027
|
+
start_nodes.sort()
|
4028
|
+
if not self.repair_border_line(start_nodes):
|
4029
|
+
logger.debug("end of create_boundery_nodes (failed)")
|
4030
|
+
return
|
4031
|
+
else:
|
4032
|
+
start_nodes = [(distance(center, n), n, True) for n in start_nodes]
|
4033
|
+
start_nodes.sort()
|
4034
|
+
|
4035
|
+
if missing_end_nodes:
|
4036
|
+
logger.debug("%s missing end nodes", len(missing_end_nodes))
|
4037
|
+
end_nodes = [(distance(center, n), n, True) for n in end_nodes]
|
4038
|
+
for n in missing_end_nodes:
|
4039
|
+
end_nodes.append((distance(center, n), n, False))
|
4040
|
+
end_nodes.sort()
|
4041
|
+
if not self.repair_border_line(end_nodes):
|
4042
|
+
logger.debug("end of create_boundery_nodes (failed)")
|
4043
|
+
return
|
4044
|
+
else:
|
4045
|
+
end_nodes = [(distance(center, n), n, True) for n in end_nodes]
|
4046
|
+
end_nodes.sort()
|
4047
|
+
|
4048
|
+
start_nodes = [(distance(center, n), n)
|
4049
|
+
for n in self.angle_nodes(center, startangle, rtol, atol)]
|
4050
|
+
start_nodes.sort()
|
4051
|
+
end_nodes = [(distance(center, n), n)
|
4052
|
+
for n in self.angle_nodes(center, endangle, rtol, atol)]
|
4053
|
+
end_nodes.sort()
|
4054
|
+
|
4055
|
+
logger.debug("End with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
|
4056
|
+
|
4057
|
+
nodes = [n for d, n in start_nodes]
|
4058
|
+
start_rot_nodes = self.rotate_nodes(alpha, nodes)
|
4059
|
+
|
4060
|
+
for d, node in start_nodes:
|
4061
|
+
self.set_point_of_node(node, node)
|
4062
|
+
i = 0
|
4063
|
+
if len(end_nodes) == len(start_rot_nodes):
|
4064
|
+
for d, node in end_nodes:
|
4065
|
+
self.set_point_of_node(node, start_rot_nodes[i])
|
4066
|
+
i += 1
|
4067
|
+
|
4068
|
+
logger.debug("end of create_boundery_nodes")
|
4069
|
+
return
|
4070
|
+
|
4071
|
+
def set_point_of_node(self, node, p):
|
4072
|
+
if isinstance(node, list):
|
4073
|
+
node = (node[0], node[1])
|
4074
|
+
nbrs = self.get_neighbors(node)
|
4075
|
+
for nbr in nbrs:
|
4076
|
+
e = self.get_edge_element(node, nbr)
|
4077
|
+
e.replace_point(node, p)
|
3848
4078
|
|
3849
4079
|
def create_and_append_area(self, n1, n2):
|
3850
4080
|
rslt = self.get_new_area(n1, n2, False)
|
@@ -3852,7 +4082,7 @@ class Geometry(object):
|
|
3852
4082
|
if rslt.get('ok', False):
|
3853
4083
|
area = rslt['area']
|
3854
4084
|
a = Area(area, self.center, 0.0)
|
3855
|
-
a.
|
4085
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3856
4086
|
self.area_list.append(a)
|
3857
4087
|
return True
|
3858
4088
|
logger.error("No area for air near airgap!!")
|
@@ -3904,7 +4134,9 @@ class Geometry(object):
|
|
3904
4134
|
self.add_line(start_cp, n,
|
3905
4135
|
color='red',
|
3906
4136
|
linestyle='dotted')
|
3907
|
-
self.
|
4137
|
+
self.add_element(start_line,
|
4138
|
+
rtol=self.rtol,
|
4139
|
+
atol=self.atol)
|
3908
4140
|
self.create_and_append_area(start_cp, n)
|
3909
4141
|
self.start_corners = self.get_corner_nodes(self.center,
|
3910
4142
|
0.0)
|
@@ -3931,7 +4163,9 @@ class Geometry(object):
|
|
3931
4163
|
self.add_line(end_cp, n,
|
3932
4164
|
color='red',
|
3933
4165
|
linestyle='dotted')
|
3934
|
-
self.
|
4166
|
+
self.add_element(end_line,
|
4167
|
+
rtol=self.rtol,
|
4168
|
+
atol=self.atol)
|
3935
4169
|
self.create_and_append_area(n, end_cp)
|
3936
4170
|
self.end_corners = self.get_corner_nodes(self.center,
|
3937
4171
|
self.alfa)
|