femagtools 1.6.8__py3-none-any.whl → 1.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- femagtools/__init__.py +2 -2
- femagtools/bch.py +1 -1
- femagtools/dxfsl/area.py +343 -406
- femagtools/dxfsl/areabuilder.py +139 -12
- femagtools/dxfsl/conv.py +27 -9
- femagtools/dxfsl/converter.py +406 -127
- 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 +1204 -893
- femagtools/dxfsl/journal.py +58 -22
- femagtools/dxfsl/machine.py +254 -75
- femagtools/dxfsl/plotrenderer.py +38 -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 +15 -12
- 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.1.dist-info}/LICENSE +1 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/METADATA +7 -4
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/RECORD +51 -50
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/WHEEL +1 -1
- tests/engines/__init__.py +0 -20
- tests/geom/__init__.py +0 -20
- tests/moo/__init__.py +0 -20
- tests/test_model.py +8 -1
- tests/test_sizing.py +2 -2
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.dist-info}/entry_points.txt +0 -0
- {femagtools-1.6.8.dist-info → femagtools-1.7.1.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,62 @@ 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
|
286
|
+
self.critical_points = []
|
324
287
|
i = 0
|
325
288
|
|
289
|
+
logger.debug("Geometry(split=%s, concat=%s, connect=%s, delete=%s, adjust=%s, main=%s,",
|
290
|
+
split, concatenate, connect, delete, adjust, main)
|
291
|
+
logger.debug(" rtol=%s, atol=%s)",
|
292
|
+
rtol, atol)
|
293
|
+
|
294
|
+
timer = Timer(start_it=True)
|
295
|
+
self.c_concat = 0
|
296
|
+
self.c_connect = 0
|
297
|
+
|
326
298
|
def get_elements(elements, split):
|
327
299
|
if split:
|
328
300
|
return intersect_and_split(elements, self.rtol, self.atol)
|
329
|
-
|
330
|
-
|
301
|
+
|
302
|
+
src_elements = [e for e in elements]
|
303
|
+
if main:
|
304
|
+
self.journal.put_elements(len(src_elements))
|
305
|
+
|
306
|
+
if not concatenate:
|
307
|
+
return src_elements
|
308
|
+
|
309
|
+
concat = Concatenation(rtol=self.rtol, atol=self.atol)
|
310
|
+
c, new_elements = concat.concatenate_matching_elements(src_elements,
|
311
|
+
main=main)
|
312
|
+
self.c_concat = c
|
313
|
+
return new_elements
|
314
|
+
|
315
|
+
nbr_nodes = []
|
316
|
+
if concatenate:
|
317
|
+
elements = [e for e in elements]
|
318
|
+
geom = Geometry(elements, center=(0.0, 0.0))
|
319
|
+
logger.debug("REAL GEOMETRY START ")
|
320
|
+
elements = geom.copy_all_elements(alpha=0.0)
|
321
|
+
nbr_nodes = geom.get_nodes(num_of_nbrs=[2, 4])
|
331
322
|
|
332
323
|
for e in get_elements(elements, split):
|
333
324
|
if e:
|
334
325
|
e.id = i
|
335
326
|
n = self.find_nodes(e.start(), e.end())
|
336
327
|
try:
|
337
|
-
|
328
|
+
self.add_or_join_edge(n[0], n[1], e,
|
329
|
+
rtol=self.rtol,
|
330
|
+
atol=self.atol)
|
338
331
|
except Exception as ex:
|
339
332
|
logger.warn("EXCEPTION %s", ex)
|
340
333
|
if e: # must be a circle
|
@@ -346,6 +339,29 @@ class Geometry(object):
|
|
346
339
|
if center:
|
347
340
|
self.set_center(center)
|
348
341
|
|
342
|
+
if connect:
|
343
|
+
self.c_connect = self.connect_all_appendices(rtol=1e-04,
|
344
|
+
atol=1e-03,
|
345
|
+
main=True)
|
346
|
+
if delete:
|
347
|
+
self.delete_all_appendices()
|
348
|
+
|
349
|
+
if concatenate and self.c_concat > 0:
|
350
|
+
self.c_connect += self.connect_all_nodes(rtol=1e-04,
|
351
|
+
atol=1e-03,
|
352
|
+
additional_nodes=nbr_nodes,
|
353
|
+
main=True)
|
354
|
+
|
355
|
+
if adjust:
|
356
|
+
self.adjust_all_points()
|
357
|
+
|
358
|
+
if delete and center:
|
359
|
+
self.set_minmax_radius()
|
360
|
+
|
361
|
+
timer.stop("-- Geometry initialised in %0.4f seconds --")
|
362
|
+
logger.debug("End Geometry(concatenated=%s, connected=%s)",
|
363
|
+
self.c_concat, self.c_connect)
|
364
|
+
|
349
365
|
def shaft(self):
|
350
366
|
"""returns shaft diameter if any"""
|
351
367
|
radius = []
|
@@ -379,8 +395,15 @@ class Geometry(object):
|
|
379
395
|
for n in self.g.nodes()}
|
380
396
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
381
397
|
|
398
|
+
def rotate_nodes(self, alpha, nodes):
|
399
|
+
T = np.array(((np.cos(alpha), -np.sin(alpha)),
|
400
|
+
(np.sin(alpha), np.cos(alpha))))
|
401
|
+
rotnodes = np.dot(T, np.asarray(nodes).T).T.tolist()
|
402
|
+
return rotnodes
|
403
|
+
|
382
404
|
def rotate(self, alpha):
|
383
405
|
"""rotates all objects by angle alpha"""
|
406
|
+
logger.debug("rotate geometry(%s)", alpha)
|
384
407
|
T = np.array(((np.cos(alpha), -np.sin(alpha)),
|
385
408
|
(np.sin(alpha), np.cos(alpha))))
|
386
409
|
for e in self.g.edges(data=True):
|
@@ -391,6 +414,7 @@ class Geometry(object):
|
|
391
414
|
mapping = {n: (round(r[0], ndec),
|
392
415
|
round(r[1], ndec))
|
393
416
|
for n, r in zip(self.g.nodes(), rotnodes)}
|
417
|
+
|
394
418
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
395
419
|
|
396
420
|
def check_geom(self, what):
|
@@ -449,12 +473,6 @@ class Geometry(object):
|
|
449
473
|
nx.relabel_nodes(self.g, mapping, copy=False)
|
450
474
|
self.diameters = tuple([factor*d for d in self.diameters])
|
451
475
|
|
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
476
|
def find_nodes(self, *points, **kwargs):
|
459
477
|
"""return closest nodes to points in arg within pickdist"""
|
460
478
|
n = []
|
@@ -475,21 +493,26 @@ class Geometry(object):
|
|
475
493
|
return [(round(p[0], ndec), round(p[1], ndec)) for p in points]
|
476
494
|
return n
|
477
495
|
|
478
|
-
def
|
479
|
-
"""return closest
|
496
|
+
def find_other_node(self, node, **kwargs):
|
497
|
+
"""return closest node to node in arg within pickdist"""
|
480
498
|
nodes = list(kwargs.get('g', self.g))
|
481
499
|
if nodes:
|
482
500
|
anodes = np.asarray(nodes)
|
483
501
|
# la.norm on numpy below 1.8 does not accept axis
|
484
|
-
c = anodes -
|
502
|
+
c = anodes - node
|
485
503
|
dist = np.sqrt(np.einsum('ij, ij->i', c, c))
|
486
|
-
# dist = la.norm(np.asarray(nodes) - p, axis=1)
|
487
504
|
idx = dist.argmin()
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
505
|
+
candidates = [(dist[i], nodes[i]) for i in range(len(dist))
|
506
|
+
if dist[i] < 0.01]
|
507
|
+
if not candidates:
|
508
|
+
return None
|
509
|
+
candidates.sort()
|
510
|
+
if len(candidates) > 1:
|
511
|
+
i = 0
|
512
|
+
d, n = candidates[0]
|
513
|
+
if d == 0.0:
|
514
|
+
d, n = candidates[1]
|
515
|
+
return n
|
493
516
|
return None
|
494
517
|
|
495
518
|
def find_the_node(self, p, **kwargs):
|
@@ -511,7 +534,7 @@ class Geometry(object):
|
|
511
534
|
paths = []
|
512
535
|
g = self.g.copy()
|
513
536
|
g.remove_edges_from(self.arcs())
|
514
|
-
while
|
537
|
+
while self.number_of_edges() > 0:
|
515
538
|
p = single_path(g.edges())
|
516
539
|
g.remove_edges_from(p)
|
517
540
|
# rearrange sequence to make it contiguous:
|
@@ -545,6 +568,69 @@ class Geometry(object):
|
|
545
568
|
return n
|
546
569
|
return []
|
547
570
|
|
571
|
+
def add_element(self, e, rtol, atol):
|
572
|
+
n = self.find_nodes(e.start(), e.end())
|
573
|
+
try:
|
574
|
+
self.add_or_join_edge(n[0], n[1], e, rtol=rtol, atol=atol)
|
575
|
+
except Exception as ex:
|
576
|
+
logger.warn("EXCEPTION in add_element: %s", ex)
|
577
|
+
|
578
|
+
def add_or_join_edge(self, n1, n2, entity, rtol=1e-03, atol=1e-03):
|
579
|
+
""" adds a new entity to graph or joins entity with existing
|
580
|
+
geom: Geometry
|
581
|
+
n1, n2: nodes
|
582
|
+
entity
|
583
|
+
"""
|
584
|
+
if n1 == n2:
|
585
|
+
logger.debug(
|
586
|
+
"add_or_join_edge: Tiny element with same node on both sides ignored: %s", n1)
|
587
|
+
logger.debug(
|
588
|
+
"add_or_join_edge: -- element: %s", entity)
|
589
|
+
return
|
590
|
+
|
591
|
+
e = self.get_edge_element(n1, n2)
|
592
|
+
if not e: # no duplicates
|
593
|
+
self.add_edge(n1, n2, entity)
|
594
|
+
return
|
595
|
+
|
596
|
+
logger.debug("add_or_join_edge: Duplicate connection: %s <--> %s", n1, n2)
|
597
|
+
if is_Line(e):
|
598
|
+
if is_Line(entity):
|
599
|
+
logger.debug("add_or_join_edge: Duplicate Lines ignored")
|
600
|
+
return # its ok
|
601
|
+
|
602
|
+
if is_Arc(e):
|
603
|
+
if is_Arc(entity):
|
604
|
+
if points_are_close(e.center, entity.center, rtol=rtol, atol=atol):
|
605
|
+
if points_are_close(e.p1, entity.p1):
|
606
|
+
logger.debug("add_or_join_edge: Duplicate Arcs ignored")
|
607
|
+
return # its ok
|
608
|
+
|
609
|
+
if is_Circle(entity):
|
610
|
+
if is_Circle(e):
|
611
|
+
logger.debug("add_or_join_edge: Duplicate Circle ignored")
|
612
|
+
return # its ok
|
613
|
+
|
614
|
+
if is_Circle(entity) or is_Circle(e):
|
615
|
+
e1, e2 = entity.cut_into_halves()
|
616
|
+
logger.debug("add_or_join_edge: Element near circle is cut into halves")
|
617
|
+
self.add_element(e1, rtol, atol)
|
618
|
+
self.add_element(e2, rtol, atol)
|
619
|
+
return # halves installed
|
620
|
+
|
621
|
+
m1 = e.center_of_connection()
|
622
|
+
m2 = entity.center_of_connection()
|
623
|
+
logger.debug("add_or_join_edge: midpoints: %s -- %s", m1, m2)
|
624
|
+
if points_are_close(m1, m2, rtol, 1e-2):
|
625
|
+
logger.debug("add_or_join_edge: Elements are close together")
|
626
|
+
return # ok
|
627
|
+
|
628
|
+
e1, e2 = entity.cut_into_halves()
|
629
|
+
logger.debug("add_or_join_edge: cut into halves")
|
630
|
+
self.add_element(e1, rtol, atol)
|
631
|
+
self.add_element(e2, rtol, atol)
|
632
|
+
return # halves installed
|
633
|
+
|
548
634
|
def add_edge(self, n1, n2, entity):
|
549
635
|
if points_are_close(n1, n2):
|
550
636
|
logger.debug("WARNING in add_edge(): Points of %s are close together",
|
@@ -552,10 +638,18 @@ class Geometry(object):
|
|
552
638
|
logger.debug(" n1 = %s, n2 = %s", n1, n2)
|
553
639
|
logger.debug(" p1 = %s, p2 = %s", entity.p1, entity.p2)
|
554
640
|
|
641
|
+
if self.has_edge(n1, n2):
|
642
|
+
logger.warning("FATAL ERROR: Duplicates in add_edge(%s, %s)", n1, n2)
|
643
|
+
|
555
644
|
entity.set_nodes(n1, n2)
|
556
645
|
logger.debug("add_edge %s - %s (%s)", n1, n2, entity.classname())
|
557
646
|
self.g.add_edge(n1, n2, object=entity)
|
558
647
|
|
648
|
+
def has_edge(self, n1, n2):
|
649
|
+
if self.g.get_edge_data(n1, n2):
|
650
|
+
return True
|
651
|
+
return False
|
652
|
+
|
559
653
|
def get_edge(self, eg):
|
560
654
|
return [[e[0], e[1], e[2]['object']] for e in self.g.edges(data=True)
|
561
655
|
if e[2]['object'] is eg]
|
@@ -574,6 +668,8 @@ class Geometry(object):
|
|
574
668
|
def _remove_edge(self, n1, n2):
|
575
669
|
logger.debug("remove_edge %s - %s", n1, n2)
|
576
670
|
self.g.remove_edge(n1, n2)
|
671
|
+
self._remove_node(n1)
|
672
|
+
self._remove_node(n2)
|
577
673
|
|
578
674
|
def remove_edge(self, edge):
|
579
675
|
e = self.get_edge(edge)
|
@@ -587,16 +683,21 @@ class Geometry(object):
|
|
587
683
|
for e in edges:
|
588
684
|
self.remove_edge(e)
|
589
685
|
|
686
|
+
def _remove_node(self, n):
|
687
|
+
for nbr in self.g.neighbors(n):
|
688
|
+
return
|
689
|
+
try:
|
690
|
+
self.g.remove_node(n)
|
691
|
+
except nx.NetworkXError:
|
692
|
+
logger.warning("WARNING: remove node %s failed", n)
|
693
|
+
|
590
694
|
def add_line(self, n1, n2, color=None, linestyle=None):
|
591
695
|
line = Line(Element(start=n1, end=n2),
|
592
696
|
color=color,
|
593
697
|
linestyle=linestyle)
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
line,
|
598
|
-
self.rtol,
|
599
|
-
self.atol)
|
698
|
+
self.add_element(line,
|
699
|
+
rtol=self.rtol,
|
700
|
+
atol=self.atol)
|
600
701
|
|
601
702
|
def add_arc(self, n1, n2, center, radius, color=None, linestyle=None):
|
602
703
|
angle_n1 = alpha_line(center, n1)
|
@@ -607,18 +708,20 @@ class Geometry(object):
|
|
607
708
|
end_angle=angle_n2*180/np.pi),
|
608
709
|
color=color,
|
609
710
|
linestyle=linestyle)
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
self.atol)
|
616
|
-
|
617
|
-
def elements(self, type):
|
711
|
+
self.add_element(arc,
|
712
|
+
rtol=self.rtol,
|
713
|
+
atol=self.atol)
|
714
|
+
|
715
|
+
def elements(self, type=Shape):
|
618
716
|
"""return lists of objects"""
|
619
717
|
return [e[2]['object'] for e in self.g.edges(data=True)
|
620
718
|
if isinstance(e[2]['object'], type)]
|
621
719
|
|
720
|
+
def elements_and_nodes(self, type=Shape):
|
721
|
+
"""return lists of objects"""
|
722
|
+
return [(e[0], e[1], e[2]['object']) for e in self.g.edges(data=True)
|
723
|
+
if isinstance(e[2]['object'], type)]
|
724
|
+
|
622
725
|
def arcs(self):
|
623
726
|
"""return lists of arcs"""
|
624
727
|
return self.elements(Arc)
|
@@ -642,12 +745,9 @@ class Geometry(object):
|
|
642
745
|
for p1, p2 in rem_lines:
|
643
746
|
self._remove_edge(p1, p2)
|
644
747
|
for new_ln in new_lines:
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
new_ln,
|
649
|
-
self.rtol,
|
650
|
-
self.atol)
|
748
|
+
self.add_element(new_ln,
|
749
|
+
rtol=self.rtol,
|
750
|
+
atol=self.atol)
|
651
751
|
|
652
752
|
def circles(self):
|
653
753
|
"""return list of circle nodes"""
|
@@ -658,8 +758,15 @@ class Geometry(object):
|
|
658
758
|
for n in self.g.nodes():
|
659
759
|
yield n
|
660
760
|
|
661
|
-
def get_nodes(self):
|
662
|
-
|
761
|
+
def get_nodes(self, num_of_nbrs=[]):
|
762
|
+
if num_of_nbrs:
|
763
|
+
nodes = []
|
764
|
+
for n in self.g.nodes():
|
765
|
+
nbr_list = [nbr for nbr in self.g.neighbors(n)]
|
766
|
+
if len(nbr_list) in num_of_nbrs:
|
767
|
+
nodes.append(n)
|
768
|
+
else:
|
769
|
+
nodes = [n for n in self.g.nodes()]
|
663
770
|
return nodes
|
664
771
|
|
665
772
|
def virtual_nodes(self):
|
@@ -668,14 +775,25 @@ class Geometry(object):
|
|
668
775
|
nodes += e.get_nodes()
|
669
776
|
return nodes
|
670
777
|
|
778
|
+
def get_neighbors(self, n):
|
779
|
+
return [nbr for nbr in self.g.neighbors(n)]
|
780
|
+
|
671
781
|
def angle_nodes(self, center, angle, rtol, atol):
|
782
|
+
if np.isclose(abs(angle), np.pi, rtol, atol):
|
783
|
+
angle_func = positive_angle
|
784
|
+
else:
|
785
|
+
angle_func = normalise_angle
|
786
|
+
angle = angle_func(angle)
|
787
|
+
|
672
788
|
nodes = []
|
673
789
|
for n in self.g.nodes():
|
674
790
|
if points_are_close(center, n, rtol, atol):
|
675
791
|
# Da gibt es keinen brauchbaren Winkel
|
676
792
|
nodes.append(n)
|
677
|
-
|
678
|
-
|
793
|
+
else:
|
794
|
+
angle_line = angle_func(alpha_line(center, n))
|
795
|
+
if np.isclose(angle, angle_line, rtol, atol):
|
796
|
+
nodes.append(n)
|
679
797
|
return nodes
|
680
798
|
|
681
799
|
def radius_nodes(self, center, radius, rtol, atol):
|
@@ -747,7 +865,10 @@ class Geometry(object):
|
|
747
865
|
else:
|
748
866
|
p = (self.min_radius, 0.0)
|
749
867
|
cp = self.start_corners[0]
|
750
|
-
if points_are_close(p, cp, atol=
|
868
|
+
if points_are_close(p, cp, rtol=1e-2, atol=1e-1):
|
869
|
+
if points_are_close(p, cp, rtol=1e-3, atol=1e-2):
|
870
|
+
logger.debug("get_start_airgap_corner: critical")
|
871
|
+
logger.debug(" -- soll: %s, ist: %s", p, cp)
|
751
872
|
return cp, True
|
752
873
|
return p, False
|
753
874
|
|
@@ -758,7 +879,11 @@ class Geometry(object):
|
|
758
879
|
else:
|
759
880
|
p = point(self.center, self.min_radius, self.alfa, ndec)
|
760
881
|
cp = self.end_corners[0]
|
761
|
-
|
882
|
+
logger.debug("End Airgap Corner: %s is %s", p, cp)
|
883
|
+
if points_are_close(p, cp, rtol=1e-2, atol=1e-1):
|
884
|
+
if points_are_close(p, cp, rtol=1e-3, atol=1e-2):
|
885
|
+
logger.debug("get_end_airgap_corner: critical")
|
886
|
+
logger.debug(" -- soll: %s, ist: %s", p, cp)
|
762
887
|
return cp, True
|
763
888
|
return p, False
|
764
889
|
|
@@ -798,6 +923,7 @@ class Geometry(object):
|
|
798
923
|
atol = 1e-3
|
799
924
|
|
800
925
|
logger.debug("begin repair_hull_line(center=%s, angle=%s)", center, angle)
|
926
|
+
[logger.debug(" --> Corner %s", c) for c in corners]
|
801
927
|
|
802
928
|
if len(corners) < 2:
|
803
929
|
# no hull without more than 1 corners
|
@@ -840,8 +966,12 @@ class Geometry(object):
|
|
840
966
|
radius=el.radius,
|
841
967
|
start_angle=alpha_mid*180/np.pi,
|
842
968
|
end_angle=alpha_end*180/np.pi))
|
843
|
-
self.
|
844
|
-
|
969
|
+
self.add_element(a1,
|
970
|
+
rtol=self.rtol,
|
971
|
+
atol=self.atol)
|
972
|
+
self.add_element(a2,
|
973
|
+
rtol=self.rtol,
|
974
|
+
atol=self.atol)
|
845
975
|
else:
|
846
976
|
clist = []
|
847
977
|
if clist_p1:
|
@@ -850,18 +980,12 @@ class Geometry(object):
|
|
850
980
|
clist = [c for c in clist_p2]
|
851
981
|
[corner.set_keep_node() for corner in clist]
|
852
982
|
|
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
983
|
# Rebuild Corner-list after correction
|
860
984
|
center_added, corners = self.get_corner_list(center, angle, rtol, atol)
|
861
985
|
for c in corners:
|
862
986
|
logger.debug("Correct Corner: %s", c)
|
863
987
|
|
864
|
-
if with_center:
|
988
|
+
if with_center or self.with_center_node:
|
865
989
|
c_corner = Corner(center, tuple(center))
|
866
990
|
if c_corner not in corners:
|
867
991
|
corners.append(c_corner)
|
@@ -871,7 +995,9 @@ class Geometry(object):
|
|
871
995
|
p1 = corners[0].point()
|
872
996
|
for c in corners[1:]:
|
873
997
|
p2 = c.point()
|
874
|
-
self.
|
998
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
999
|
+
rtol=self.rtol,
|
1000
|
+
atol=self.atol)
|
875
1001
|
p1 = p2
|
876
1002
|
|
877
1003
|
self.set_minmax_radius()
|
@@ -906,14 +1032,18 @@ class Geometry(object):
|
|
906
1032
|
c_min.is_new_point = True
|
907
1033
|
p1 = c_min.point()
|
908
1034
|
p2 = c_first.point()
|
909
|
-
self.
|
1035
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
1036
|
+
rtol=self.rtol,
|
1037
|
+
atol=self.atol)
|
910
1038
|
|
911
1039
|
c_last = corners[len(corners)-1]
|
912
1040
|
if not c_max.is_same_corner(c_last):
|
913
1041
|
c_max.is_new_point = True
|
914
1042
|
p2 = c_max.point()
|
915
1043
|
p1 = c_last.point()
|
916
|
-
self.
|
1044
|
+
self.add_element(Line(Element(start=p1, end=p2)),
|
1045
|
+
rtol=self.rtol,
|
1046
|
+
atol=self.atol)
|
917
1047
|
logger.debug("end complete_hull_line")
|
918
1048
|
return (c_min, c_max)
|
919
1049
|
|
@@ -928,10 +1058,12 @@ class Geometry(object):
|
|
928
1058
|
nodes_sorted.sort()
|
929
1059
|
p = nodes_sorted[0][1]
|
930
1060
|
angle_p = alpha_line(self.center, p)
|
931
|
-
self.
|
932
|
-
|
933
|
-
|
934
|
-
|
1061
|
+
arc = Arc(Element(center=self.center, radius=radius,
|
1062
|
+
start_angle=startangle*180/np.pi,
|
1063
|
+
end_angle=angle_p*180/np.pi))
|
1064
|
+
self.add_element(arc,
|
1065
|
+
rtol=self.rtol,
|
1066
|
+
atol=self.atol)
|
935
1067
|
|
936
1068
|
if endcorner.is_new_point:
|
937
1069
|
end_p = endcorner.point()
|
@@ -940,10 +1072,12 @@ class Geometry(object):
|
|
940
1072
|
inx = len(nodes_sorted)-1
|
941
1073
|
p = nodes_sorted[inx][1]
|
942
1074
|
angle_p = alpha_line(self.center, p)
|
943
|
-
self.
|
944
|
-
|
945
|
-
|
946
|
-
|
1075
|
+
arc = Arc(Element(center=self.center, radius=radius,
|
1076
|
+
start_angle=angle_p*180/np.pi,
|
1077
|
+
end_angle=endangle*180/np.pi))
|
1078
|
+
self.add_element(p, end_p, arc,
|
1079
|
+
rtol=self.rtol,
|
1080
|
+
atol=self.atol)
|
947
1081
|
|
948
1082
|
def get_corner_nodes(self, center, angle):
|
949
1083
|
rtol = 1e-4
|
@@ -954,313 +1088,17 @@ class Geometry(object):
|
|
954
1088
|
return () # not enough corners
|
955
1089
|
return (corners[0].point(), corners[len(corners)-1].point())
|
956
1090
|
|
1091
|
+
def set_start_corners(self, center, angle):
|
1092
|
+
self.start_corners = self.get_corner_nodes(center, angle)
|
1093
|
+
|
1094
|
+
def set_end_corners(self, center, angle):
|
1095
|
+
self.end_corners = self.get_corner_nodes(center, angle)
|
1096
|
+
|
957
1097
|
def get_angle(self, alpha1, alpha2):
|
958
1098
|
if np.isclose(alpha1, alpha2, 0.001, 0.001):
|
959
1099
|
return 0.0
|
960
1100
|
return alpha_angle(alpha1, alpha2)
|
961
1101
|
|
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
1102
|
def set_edge_attributes(self):
|
1265
1103
|
if nxversion == 1:
|
1266
1104
|
nx.set_edge_attributes(self.g, 0, True)
|
@@ -1271,7 +1109,7 @@ class Geometry(object):
|
|
1271
1109
|
nx.set_edge_attributes(self.g, False, 1)
|
1272
1110
|
nx.set_edge_attributes(self.g, False, 2)
|
1273
1111
|
|
1274
|
-
def create_list_of_areas(self,
|
1112
|
+
def create_list_of_areas(self, main=False):
|
1275
1113
|
""" return list of areas for each node and their neighbors
|
1276
1114
|
"""
|
1277
1115
|
if len(self.area_list) > 0:
|
@@ -1280,47 +1118,9 @@ class Geometry(object):
|
|
1280
1118
|
return
|
1281
1119
|
|
1282
1120
|
areabuilder = AreaBuilder(geom=self)
|
1283
|
-
areabuilder.create_list_of_areas(main=
|
1121
|
+
areabuilder.create_list_of_areas(main=main)
|
1284
1122
|
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)
|
1123
|
+
logger.debug("area list created")
|
1324
1124
|
|
1325
1125
|
def list_of_areas(self):
|
1326
1126
|
self.create_list_of_areas()
|
@@ -1497,8 +1297,12 @@ class Geometry(object):
|
|
1497
1297
|
end_angle=alpha_end*180/np.pi))
|
1498
1298
|
if points_are_close(a.p1, a.p2, rtol=1e-02, atol=1e-02):
|
1499
1299
|
logger.debug("ATTENTION: creation of a tiny arc")
|
1300
|
+
logger.debug("-- %s", a)
|
1500
1301
|
a.set_attribute("tiny")
|
1501
|
-
|
1302
|
+
if points_are_close(a.p1, a.p2, rtol=1e-06, atol=1e-06):
|
1303
|
+
logger.debug("-- points are equal")
|
1304
|
+
else:
|
1305
|
+
new_elements.append(a)
|
1502
1306
|
alpha_start = alpha_end
|
1503
1307
|
p1 = p2
|
1504
1308
|
return new_elements
|
@@ -1594,7 +1398,8 @@ class Geometry(object):
|
|
1594
1398
|
append_inner=False,
|
1595
1399
|
append_outer=False,
|
1596
1400
|
delete_appendices=False,
|
1597
|
-
|
1401
|
+
concatenate=True,
|
1402
|
+
connect=True):
|
1598
1403
|
""" Die Funktion kopiert die Teile von Shape-Objekten, welche sich in
|
1599
1404
|
der durch die Parameter definierten Teilkreisfläche befinden.
|
1600
1405
|
"""
|
@@ -1608,6 +1413,8 @@ class Geometry(object):
|
|
1608
1413
|
atol = 1e-4
|
1609
1414
|
logger.debug(' -> rtol=%s, atol=%s', rtol, atol)
|
1610
1415
|
|
1416
|
+
self.with_center_node = self.find_the_node(self.center) is not None
|
1417
|
+
|
1611
1418
|
if is_same_angle(startangle, endangle):
|
1612
1419
|
start_line = Line(
|
1613
1420
|
Element(start=self.center,
|
@@ -1695,40 +1502,28 @@ class Geometry(object):
|
|
1695
1502
|
new_elements.append(arc)
|
1696
1503
|
p1 = p2
|
1697
1504
|
|
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
|
1505
|
+
center = self.center
|
1707
1506
|
|
1708
1507
|
if split:
|
1709
1508
|
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)
|
1509
|
+
|
1510
|
+
geom = Geometry(new_elements,
|
1511
|
+
center=center,
|
1512
|
+
rtol=self.rtol,
|
1513
|
+
atol=self.atol,
|
1514
|
+
is_inner=self.is_inner,
|
1515
|
+
is_outer=self.is_outer,
|
1516
|
+
concatenate=concatenate,
|
1517
|
+
connect=connect,
|
1518
|
+
delete=delete_appendices,
|
1519
|
+
split=split)
|
1520
|
+
geom.with_center_node = self.with_center_node
|
1521
|
+
|
1728
1522
|
logger.debug('end copy_shape')
|
1729
1523
|
return geom
|
1730
1524
|
|
1731
1525
|
def copy_all_elements(self, alpha):
|
1526
|
+
logger.debug("begin copy_all_elements(alpha=%s)", alpha)
|
1732
1527
|
if alpha == 0.0:
|
1733
1528
|
T = None
|
1734
1529
|
else:
|
@@ -1764,19 +1559,25 @@ class Geometry(object):
|
|
1764
1559
|
el.transform(T, alpha, ndec)
|
1765
1560
|
all_el.append(el)
|
1766
1561
|
|
1767
|
-
logger.debug("copy_all_elements: %s lines, %s arcs, %s circles",
|
1562
|
+
logger.debug("end copy_all_elements: %s lines, %s arcs, %s circles",
|
1768
1563
|
lines, arcs, circles)
|
1769
|
-
|
1770
1564
|
return all_el
|
1771
1565
|
|
1772
|
-
def new_clone(self, new_elements,
|
1566
|
+
def new_clone(self, new_elements,
|
1567
|
+
split=False,
|
1568
|
+
concatenate=False,
|
1569
|
+
connect=False,
|
1570
|
+
adjust=False):
|
1773
1571
|
return Geometry(new_elements,
|
1774
1572
|
center=self.center,
|
1775
1573
|
rtol=self.rtol,
|
1776
1574
|
atol=self.atol,
|
1777
1575
|
is_inner=self.is_inner,
|
1778
1576
|
is_outer=self.is_outer,
|
1779
|
-
split=split
|
1577
|
+
split=split,
|
1578
|
+
concatenate=concatenate,
|
1579
|
+
connect=connect,
|
1580
|
+
adjust=adjust)
|
1780
1581
|
|
1781
1582
|
def is_new_angle(self, alpha_list, alpha):
|
1782
1583
|
for a in alpha_list:
|
@@ -1784,78 +1585,6 @@ class Geometry(object):
|
|
1784
1585
|
return False
|
1785
1586
|
return True
|
1786
1587
|
|
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
1588
|
def find_symmetry(self, radius,
|
1860
1589
|
startangle, endangle, sym_tolerance):
|
1861
1590
|
arealist = self.list_of_areas()
|
@@ -2082,6 +1811,29 @@ class Geometry(object):
|
|
2082
1811
|
return [h for (k, h) in legend.items()]
|
2083
1812
|
return []
|
2084
1813
|
|
1814
|
+
def render_areagroups(self, renderer):
|
1815
|
+
if not self.areagroup_list:
|
1816
|
+
return
|
1817
|
+
for area in self.areagroup_list:
|
1818
|
+
area.render(renderer,
|
1819
|
+
color="yellow",
|
1820
|
+
fill=False)
|
1821
|
+
return
|
1822
|
+
|
1823
|
+
def render_magnet_phi(self, renderer):
|
1824
|
+
magnets = [a for a in self.list_of_areas()]
|
1825
|
+
if not magnets:
|
1826
|
+
return
|
1827
|
+
arrow_len = [a.magnet_arrow_length() for a in magnets]
|
1828
|
+
length = max(arrow_len)
|
1829
|
+
|
1830
|
+
for area in magnets:
|
1831
|
+
area.render_magnet_phi(renderer, length)
|
1832
|
+
|
1833
|
+
def render_critical(self, renderer):
|
1834
|
+
for e in self.critical_points:
|
1835
|
+
e.render(renderer, 'darkred')
|
1836
|
+
|
2085
1837
|
def get_points_in_iron(self):
|
2086
1838
|
points = []
|
2087
1839
|
for area in self.list_of_areas():
|
@@ -2114,6 +1866,10 @@ class Geometry(object):
|
|
2114
1866
|
atol = 3.0
|
2115
1867
|
|
2116
1868
|
logger.debug("*** Begin of get_machine() ***")
|
1869
|
+
|
1870
|
+
logger.debug(">> minmax: %s", mm)
|
1871
|
+
logger.debug(">> w=%s, h=%s", width, height)
|
1872
|
+
|
2117
1873
|
if np.isclose(height, width, self.rtol, self.atol):
|
2118
1874
|
radius = width/2
|
2119
1875
|
self.set_center([mm[1]-radius, mm[3]-radius])
|
@@ -2128,6 +1884,8 @@ class Geometry(object):
|
|
2128
1884
|
logger.info("check for quarter machine")
|
2129
1885
|
radius = width
|
2130
1886
|
self.set_center([mm[0], mm[2]])
|
1887
|
+
logger.debug("-- center = %s, radius min/max = %s/%s",
|
1888
|
+
self.center, self.min_radius, self.max_radius)
|
2131
1889
|
if self.check_hull(radius, mm[0], mm[2], self.rtol, atol):
|
2132
1890
|
logger.info(" - it is a quarter")
|
2133
1891
|
return Machine(self,
|
@@ -2303,7 +2061,7 @@ class Geometry(object):
|
|
2303
2061
|
m_min = min(m_min, m)
|
2304
2062
|
|
2305
2063
|
y = line_n([p[0]-center[0], p[1]], m_min)
|
2306
|
-
center[
|
2064
|
+
center = (center[0], y)
|
2307
2065
|
angle = alpha_line(center, p)
|
2308
2066
|
|
2309
2067
|
self.set_center([round(center[0], 8), round(center[1], 8)])
|
@@ -2406,8 +2164,20 @@ class Geometry(object):
|
|
2406
2164
|
return None
|
2407
2165
|
|
2408
2166
|
def get_center_arcs(self):
|
2167
|
+
logger.debug("begin of get_center_arcs")
|
2409
2168
|
center_list = []
|
2410
|
-
for e in self.elements(
|
2169
|
+
circles = [e for e in self.elements() if is_Circle(e)]
|
2170
|
+
logger.debug(" -- %s Circles", len(circles))
|
2171
|
+
|
2172
|
+
for e in circles:
|
2173
|
+
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2174
|
+
radius = round(e.radius, 1)
|
2175
|
+
center_list.append(([1], center, [radius]))
|
2176
|
+
|
2177
|
+
arcs = [e for e in self.elements() if is_Arc(e)]
|
2178
|
+
logger.debug(" -- %s Arcs", len(arcs))
|
2179
|
+
|
2180
|
+
for e in arcs:
|
2411
2181
|
center = (round(e.center[0], 3), round(e.center[1], 3))
|
2412
2182
|
radius = round(e.radius, 1)
|
2413
2183
|
c = self.get_same_center(center_list, center, self.rtol, self.atol)
|
@@ -2429,6 +2199,8 @@ class Geometry(object):
|
|
2429
2199
|
c2 = arc_list[1]
|
2430
2200
|
if not c1[0] > c2[0]:
|
2431
2201
|
center = None
|
2202
|
+
|
2203
|
+
logger.debug("end of get_center_arcs: -> %s", center)
|
2432
2204
|
return center
|
2433
2205
|
|
2434
2206
|
def get_center_dim(self, mm):
|
@@ -2487,6 +2259,63 @@ class Geometry(object):
|
|
2487
2259
|
borders += 1
|
2488
2260
|
return (ok, borders)
|
2489
2261
|
|
2262
|
+
def check_airgap(self, startangle, endangle):
|
2263
|
+
logger.debug("begin check_airgap")
|
2264
|
+
area_id_list = [a.id for a in self.list_of_areas()]
|
2265
|
+
|
2266
|
+
def delete_id(id):
|
2267
|
+
try:
|
2268
|
+
i = area_id_list.index(id)
|
2269
|
+
except ValueError:
|
2270
|
+
return
|
2271
|
+
area_id_list[i] = 0
|
2272
|
+
# ---
|
2273
|
+
def append_area(alist, a):
|
2274
|
+
for my_a in alist:
|
2275
|
+
if my_a.is_in_touch_with_area(self, a):
|
2276
|
+
alist.append(a)
|
2277
|
+
delete_id(a.id)
|
2278
|
+
return True
|
2279
|
+
return False
|
2280
|
+
# ---
|
2281
|
+
for area in self.area_list:
|
2282
|
+
if not area.id in area_id_list:
|
2283
|
+
continue
|
2284
|
+
|
2285
|
+
for a in self.area_list:
|
2286
|
+
if area.id == a.id:
|
2287
|
+
continue
|
2288
|
+
if not a.id in area_id_list:
|
2289
|
+
continue
|
2290
|
+
|
2291
|
+
if area.the_area_is_inside_area(a):
|
2292
|
+
delete_id(a.id)
|
2293
|
+
|
2294
|
+
# collect remaining areas
|
2295
|
+
area_list = [a for a in self.area_list if a.id in area_id_list]
|
2296
|
+
group_list = {}
|
2297
|
+
for area in area_list:
|
2298
|
+
if not area.id in area_id_list:
|
2299
|
+
continue
|
2300
|
+
group_list[area.id] = [area]
|
2301
|
+
delete_id(area.id)
|
2302
|
+
for a in self.area_list:
|
2303
|
+
if area.id == a.id:
|
2304
|
+
continue
|
2305
|
+
if not a.id in area_id_list:
|
2306
|
+
continue
|
2307
|
+
if append_area(group_list[area.id], a):
|
2308
|
+
continue
|
2309
|
+
|
2310
|
+
area_list = [a for a in self.area_list if a.id in area_id_list]
|
2311
|
+
for area in area_list:
|
2312
|
+
group_list[area.id] = [area]
|
2313
|
+
|
2314
|
+
area_id_list = [int(x) for x in group_list.keys()]
|
2315
|
+
|
2316
|
+
logger.debug("end check_airgap: return %s", len(area_id_list) > 1)
|
2317
|
+
return len(area_id_list) > 1 # bad
|
2318
|
+
|
2490
2319
|
def is_border_line(self, center, startangle, endangle, e, atol):
|
2491
2320
|
if isinstance(e, Line):
|
2492
2321
|
if np.isclose(startangle, endangle):
|
@@ -2635,6 +2464,49 @@ class Geometry(object):
|
|
2635
2464
|
# logger.info(" ++ %s", id)
|
2636
2465
|
logger.debug("end set_areas_inside_for_all_areas")
|
2637
2466
|
|
2467
|
+
def set_groups_inside_for_all_areas(self):
|
2468
|
+
logger.debug("begin set_groups_inside_for_all_areas")
|
2469
|
+
|
2470
|
+
groups_inside = {}
|
2471
|
+
groups = {}
|
2472
|
+
areas_outside = []
|
2473
|
+
for area in self.list_of_areas():
|
2474
|
+
grouplist = [a for a in self.areagroup_list
|
2475
|
+
if area.is_inside(a, self)]
|
2476
|
+
if not grouplist:
|
2477
|
+
continue
|
2478
|
+
groups_inside = {g.id: g for g in grouplist}
|
2479
|
+
area.areas_inside = groups_inside
|
2480
|
+
areas_outside.append(area)
|
2481
|
+
for g in grouplist:
|
2482
|
+
alist = groups.get(g.id, [])
|
2483
|
+
alist.append(area)
|
2484
|
+
groups[g.id] = alist
|
2485
|
+
|
2486
|
+
outside_id = [a.id for a in areas_outside]
|
2487
|
+
logger.debug("Areas outside: %s", outside_id)
|
2488
|
+
|
2489
|
+
for id in groups.keys():
|
2490
|
+
if len(groups[id]) > 1:
|
2491
|
+
logger.warning("Attention: nested groups of areas")
|
2492
|
+
self.journal.put("warning", "nested groups of areas")
|
2493
|
+
areas = groups[id]
|
2494
|
+
main_area = areas[0]
|
2495
|
+
main_size = main_area.area_size()
|
2496
|
+
for a in areas[1:]:
|
2497
|
+
sz = a.area_size()
|
2498
|
+
if sz < main_size:
|
2499
|
+
main_area = a
|
2500
|
+
main_size = sz
|
2501
|
+
assert(main_area is not None)
|
2502
|
+
main_area.is_child = True
|
2503
|
+
for area in areas:
|
2504
|
+
if area.id != main_area.id:
|
2505
|
+
del area.areas_inside[id]
|
2506
|
+
|
2507
|
+
logger.debug("end set_areas_inside_for_all_areas")
|
2508
|
+
return areas_outside
|
2509
|
+
|
2638
2510
|
def get_minmax_magnet(self):
|
2639
2511
|
logger.debug("get_minmax_magnet")
|
2640
2512
|
maglist = [a for a in self.list_of_areas() if a.is_magnet()]
|
@@ -2647,15 +2519,29 @@ class Geometry(object):
|
|
2647
2519
|
|
2648
2520
|
def create_auxiliary_lines(self, rightangle, leftangle):
|
2649
2521
|
logger.debug("begin of create_auxiliary_lines")
|
2650
|
-
|
2651
|
-
|
2652
|
-
logger.debug("-> start create_auxiliary_lines")
|
2653
|
-
|
2522
|
+
timer = Timer(start_it=True)
|
2654
2523
|
done = False
|
2655
|
-
for area in self.list_of_areas():
|
2656
|
-
if self.create_aux_lines(area, rightangle, leftangle):
|
2657
|
-
done = True
|
2658
2524
|
|
2525
|
+
if True: # new style
|
2526
|
+
logger.debug("-> start create_auxiliary_lines")
|
2527
|
+
area_list = self.list_of_areas()
|
2528
|
+
builder = AreaBuilder(geom=self)
|
2529
|
+
builder.create_area_groups(area_list)
|
2530
|
+
self.areagroup_list = builder.area_list
|
2531
|
+
area_list = self.set_groups_inside_for_all_areas()
|
2532
|
+
for area in area_list:
|
2533
|
+
if self.create_aux_lines(area, rightangle, leftangle):
|
2534
|
+
done = True
|
2535
|
+
else:
|
2536
|
+
logger.debug("-> start create_auxiliary_lines")
|
2537
|
+
self.set_areas_inside_for_all_areas()
|
2538
|
+
done = False
|
2539
|
+
for area in self.list_of_areas():
|
2540
|
+
if self.create_aux_lines(area, rightangle, leftangle):
|
2541
|
+
done = True
|
2542
|
+
|
2543
|
+
t = timer.stop("-- auxiliary lines in %0.4f seconds --")
|
2544
|
+
self.journal.put('time_auxiliary_lines', t)
|
2659
2545
|
logger.debug("end of create_auxiliary_lines")
|
2660
2546
|
return done
|
2661
2547
|
|
@@ -2664,7 +2550,7 @@ class Geometry(object):
|
|
2664
2550
|
|
2665
2551
|
areas_inside = area.areas_inside.values()
|
2666
2552
|
if not areas_inside:
|
2667
|
-
logger.debug("end create_aux_lines() for %s (no areas inside)",
|
2553
|
+
logger.debug("end of create_aux_lines() for %s (no areas inside)",
|
2668
2554
|
area.get_id())
|
2669
2555
|
return False
|
2670
2556
|
|
@@ -2672,6 +2558,10 @@ class Geometry(object):
|
|
2672
2558
|
|
2673
2559
|
aux_color = 'red'
|
2674
2560
|
aux_linestyle = 'dotted'
|
2561
|
+
if area.is_child:
|
2562
|
+
logger.debug("Area %s is a child of another nested area", area.id)
|
2563
|
+
rightangle = None
|
2564
|
+
leftangle = None
|
2675
2565
|
|
2676
2566
|
areas_border = {a.get_id(): a for a in areas_inside
|
2677
2567
|
if area.has_connection(self, a, ndec)}
|
@@ -2861,21 +2751,22 @@ class Geometry(object):
|
|
2861
2751
|
line = aux_line['line']
|
2862
2752
|
n1 = self.find_the_node(aux_line['p1'])
|
2863
2753
|
n2 = self.find_the_node(aux_line['p2'])
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2871
|
-
|
2754
|
+
logger.debug("Line: n1=%s, n2=%s", n1, n2)
|
2755
|
+
|
2756
|
+
pts = self.split_and_get_intersect_points(line)
|
2757
|
+
if len(pts) != 2:
|
2758
|
+
logger.error("ERROR in create_aux_lines()")
|
2759
|
+
logger.debug("Points: %s", pts)
|
2760
|
+
logger.debug("Line: %s", line)
|
2761
|
+
|
2762
|
+
n1 = self.find_the_node(line.node1(ndec))
|
2763
|
+
n2 = self.find_the_node(line.node2(ndec))
|
2764
|
+
logger.debug("Line: n1=%s, n2=%s", n1, n2)
|
2872
2765
|
if n1 and n2:
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
self.rtol,
|
2878
|
-
self.atol)
|
2766
|
+
logger.debug("Create Line %s", aux_line['pattern'])
|
2767
|
+
self.add_element(line,
|
2768
|
+
rtol=self.rtol,
|
2769
|
+
atol=self.atol)
|
2879
2770
|
logger.debug("=== Create auxiliary line: %s", aux_line)
|
2880
2771
|
if aux_line['connect'] == 'child':
|
2881
2772
|
for a in areas_inside:
|
@@ -2889,7 +2780,7 @@ class Geometry(object):
|
|
2889
2780
|
logger.debug("end create_aux_lines() for %s (no iron)",
|
2890
2781
|
area.get_id())
|
2891
2782
|
return done
|
2892
|
-
|
2783
|
+
return done
|
2893
2784
|
# -----------------
|
2894
2785
|
def id_of_inside_area(p):
|
2895
2786
|
for a in areas_inside:
|
@@ -2925,7 +2816,10 @@ class Geometry(object):
|
|
2925
2816
|
# ----------
|
2926
2817
|
|
2927
2818
|
# Arcs as additional auxiliary connections thru iron
|
2819
|
+
logger.debug("Additional Lines in %s", area.identifier())
|
2928
2820
|
for a in area_to_parent_list:
|
2821
|
+
logger.debug("Area %s in Parent List", a.identifier())
|
2822
|
+
|
2929
2823
|
mid_dist = (a.min_dist + a.max_dist) / 2
|
2930
2824
|
mid_angle = (a.min_angle + a.max_angle) / 2
|
2931
2825
|
arc = Arc(Element(center=self.center,
|
@@ -2949,12 +2843,14 @@ class Geometry(object):
|
|
2949
2843
|
radius=mid_dist,
|
2950
2844
|
start_angle=start_angle*180/np.pi,
|
2951
2845
|
end_angle=end_angle*180/np.pi),
|
2952
|
-
color=aux_color,
|
2846
|
+
color='black', #aux_color,
|
2953
2847
|
linestyle=aux_linestyle)
|
2954
2848
|
arc.set_attribute('iron_sep')
|
2955
2849
|
self.split_and_get_intersect_points(arc)
|
2956
2850
|
n = self.find_nodes(pts[0], pts[1])
|
2957
|
-
self.
|
2851
|
+
self.add_or_join_edge(n[0], n[1], arc,
|
2852
|
+
rtol=self.rtol,
|
2853
|
+
atol=self.atol)
|
2958
2854
|
|
2959
2855
|
logger.debug("end create_aux_lines() for %s",
|
2960
2856
|
area.get_id())
|
@@ -3000,53 +2896,99 @@ class Geometry(object):
|
|
3000
2896
|
dict12['deleted'] = True
|
3001
2897
|
dict01['deleted'] = True
|
3002
2898
|
line = Line(Element(start=n0, end=n2))
|
3003
|
-
self.
|
2899
|
+
self.add_element(line,
|
2900
|
+
rtol=self.rtol,
|
2901
|
+
atol=self.atol)
|
3004
2902
|
return True
|
3005
2903
|
|
3006
|
-
def
|
2904
|
+
def search_tiny_elements(self, mindist):
|
2905
|
+
logger.debug("begin of search_tiny_elements(%s)", mindist)
|
3007
2906
|
if mindist == 0.0:
|
3008
|
-
return
|
2907
|
+
return []
|
3009
2908
|
|
3010
2909
|
edges = [edge for edge in self.g.edges(data=True)
|
3011
2910
|
if distance(edge[0], edge[1]) < mindist]
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
2911
|
+
|
2912
|
+
logger.debug("end of search_tiny_elements: %s tiny elements found",
|
2913
|
+
len(edges))
|
2914
|
+
return edges
|
2915
|
+
|
2916
|
+
def delete_tiny_elements(self, mindist):
|
2917
|
+
logger.debug("begin of delete_tiny_elements(%s)", mindist)
|
2918
|
+
edges = self.search_tiny_elements(mindist)
|
2919
|
+
if not edges:
|
2920
|
+
logger.debug("-- no tiny elements found")
|
2921
|
+
return 0
|
2922
|
+
|
3015
2923
|
deleted = 0
|
3016
2924
|
for edge in edges:
|
3017
|
-
|
2925
|
+
n1 = edge[0]
|
2926
|
+
n2 = edge[1]
|
2927
|
+
el = edge[2]['object']
|
2928
|
+
logger.debug("-- %s: %s <-> %s", el.classname(), n1, n2)
|
2929
|
+
logger.debug("Edge: %s", el.classname())
|
2930
|
+
|
2931
|
+
if n1 is n2:
|
2932
|
+
logger.debug("-- delete edge with equal nodes")
|
2933
|
+
self._remove_edge(n1, n2)
|
2934
|
+
deleted += 1
|
3018
2935
|
continue
|
3019
2936
|
|
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
|
2937
|
+
nbrs_n1 = [nbr for nbr in self.g.neighbors(n1)
|
2938
|
+
if not nodes_are_equal(nbr, n2)]
|
2939
|
+
nbrs_n2 = [nbr for nbr in self.g.neighbors(n2)
|
2940
|
+
if not nodes_are_equal(nbr, n1)]
|
2941
|
+
|
2942
|
+
if len(nbrs_n1) == 0 and len(nbrs_n2) == 0:
|
2943
|
+
# lonesome edge
|
2944
|
+
logger.debug("-- delete lonesome edge")
|
2945
|
+
self._remove_edge(n1, n2)
|
2946
|
+
deleted += 1
|
2947
|
+
continue
|
3024
2948
|
|
3025
2949
|
if len(nbrs_n1) == 1:
|
3026
|
-
if self._delete_a_tiny_element(edge[
|
3027
|
-
edge[2], nbrs_n1[0]):
|
2950
|
+
if self._delete_a_tiny_element(n2, n1, edge[2], nbrs_n1[0]):
|
3028
2951
|
deleted += 1
|
3029
2952
|
continue
|
3030
2953
|
|
3031
2954
|
if len(nbrs_n2) == 1:
|
3032
|
-
if self._delete_a_tiny_element(edge[
|
3033
|
-
edge[2], nbrs_n2[0]):
|
2955
|
+
if self._delete_a_tiny_element(n1, n2, edge[2], nbrs_n2[0]):
|
3034
2956
|
deleted += 1
|
3035
2957
|
continue
|
3036
2958
|
|
3037
2959
|
if deleted:
|
3038
|
-
logger.
|
3039
|
-
|
2960
|
+
logger.debug("%s tiny elements deleted", deleted)
|
2961
|
+
self.journal.put("tiny_elements_deleted", deleted)
|
2962
|
+
logger.debug("end of delete_tiny_elements")
|
2963
|
+
return deleted
|
2964
|
+
|
2965
|
+
def search_critical_elements(self, mindist):
|
2966
|
+
for n in self.g.nodes():
|
2967
|
+
nbrs = self.get_neighbors(n)
|
2968
|
+
if len(nbrs) < 3:
|
2969
|
+
continue
|
2970
|
+
critical_point = False
|
2971
|
+
critical_dist = 9999
|
2972
|
+
for nbr in nbrs:
|
2973
|
+
e = self.get_edge_element(n, nbr)
|
2974
|
+
if e.is_tiny(mindist):
|
2975
|
+
critical_point = True
|
2976
|
+
critical_dist = min(critical_dist, e.length())
|
2977
|
+
if critical_point:
|
2978
|
+
logger.debug("Warning: maybe critical point %s", n)
|
2979
|
+
self.journal.put("maybe_critical_points", (n, critical_dist))
|
2980
|
+
c = Circle(Element(center=n, radius=1))
|
2981
|
+
self.critical_points.append(c)
|
3040
2982
|
|
3041
2983
|
def check_shaft_area(self, shaft):
|
3042
2984
|
for a in self.list_of_areas():
|
3043
2985
|
if not shaft.is_identical(a):
|
3044
2986
|
if shaft.is_inside(a, self):
|
3045
|
-
shaft.
|
2987
|
+
shaft.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3046
2988
|
return
|
3047
2989
|
if shaft.is_touching(a):
|
3048
2990
|
if not a.is_iron():
|
3049
|
-
shaft.
|
2991
|
+
shaft.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3050
2992
|
return
|
3051
2993
|
|
3052
2994
|
def mark_connecting_edges(self, windings):
|
@@ -3060,18 +3002,19 @@ class Geometry(object):
|
|
3060
3002
|
for e in elist:
|
3061
3003
|
e.init_attributes('lightblue', 'no_fsl')
|
3062
3004
|
|
3063
|
-
def search_subregions(self):
|
3005
|
+
def search_subregions(self, startangle, endangle, single=False):
|
3064
3006
|
if self.is_stator():
|
3065
|
-
self.search_stator_subregions()
|
3007
|
+
self.search_stator_subregions(startangle, endangle, single=single)
|
3066
3008
|
elif self.is_rotor():
|
3067
|
-
self.search_rotor_subregions()
|
3009
|
+
self.search_rotor_subregions(startangle, endangle, single=single)
|
3068
3010
|
else:
|
3069
3011
|
logger.warning("no stator or rotor assigned")
|
3070
3012
|
self.search_unknown_subregions()
|
3071
3013
|
self.looking_for_corners()
|
3072
3014
|
|
3073
3015
|
def get_windings(self, type):
|
3074
|
-
windings = [a for a in self.list_of_areas()
|
3016
|
+
windings = [a for a in self.list_of_areas()
|
3017
|
+
if a.is_type(type)]
|
3075
3018
|
for w in windings:
|
3076
3019
|
inside = []
|
3077
3020
|
for a in self.list_of_areas():
|
@@ -3079,13 +3022,14 @@ class Geometry(object):
|
|
3079
3022
|
if w.is_inside(a, self):
|
3080
3023
|
inside.append(a)
|
3081
3024
|
if inside:
|
3082
|
-
w.set_type(
|
3083
|
-
return [a for a in self.list_of_areas()
|
3025
|
+
w.set_type(AREA.TYPE_AIR) # air
|
3026
|
+
return [a for a in self.list_of_areas()
|
3027
|
+
if a.is_type(type)]
|
3084
3028
|
|
3085
3029
|
def collect_windings(self):
|
3086
3030
|
logger.debug("begin of collect_windings")
|
3087
|
-
good_windings = self.get_windings(
|
3088
|
-
ugly_windings = self.get_windings(
|
3031
|
+
good_windings = self.get_windings(AREA.TYPE_WINDINGS)
|
3032
|
+
ugly_windings = self.get_windings(AREA.TYPE_WINDINGS_OR_AIR)
|
3089
3033
|
|
3090
3034
|
logger.debug("-- %s good and %s ugly windings",
|
3091
3035
|
len(good_windings),
|
@@ -3097,8 +3041,8 @@ class Geometry(object):
|
|
3097
3041
|
|
3098
3042
|
if not good_windings:
|
3099
3043
|
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.
|
3044
|
+
[w.set_type(AREA.TYPE_WINDINGS) for w in ugly_windings]
|
3045
|
+
return [a for a in self.list_of_areas() if a.is_type(AREA.TYPE_WINDINGS)]
|
3102
3046
|
|
3103
3047
|
# ggod and ugly windings available
|
3104
3048
|
found = True
|
@@ -3106,27 +3050,28 @@ class Geometry(object):
|
|
3106
3050
|
found = False
|
3107
3051
|
for a in ugly_windings:
|
3108
3052
|
if a.is_touching_areas(good_windings):
|
3109
|
-
a.set_type(
|
3053
|
+
a.set_type(AREA.TYPE_WINDINGS)
|
3110
3054
|
found = True
|
3111
3055
|
|
3112
|
-
good_windings = [a for a in self.list_of_areas()
|
3113
|
-
|
3056
|
+
good_windings = [a for a in self.list_of_areas()
|
3057
|
+
if a.is_type(AREA.TYPE_WINDINGS)]
|
3058
|
+
ugly_windings = [a for a in self.list_of_areas()
|
3059
|
+
if a.is_type(AREA.TYPE_WINDINGS_OR_AIR)]
|
3114
3060
|
|
3115
|
-
[w.set_type(
|
3116
|
-
good_windings = [a for a in self.list_of_areas()
|
3061
|
+
[w.set_type(AREA.TYPE_AIR) for w in ugly_windings]
|
3062
|
+
good_windings = [a for a in self.list_of_areas()
|
3063
|
+
if a.is_type(AREA.TYPE_WINDINGS)]
|
3117
3064
|
|
3118
|
-
logger.debug("return
|
3065
|
+
logger.debug("return bad and ugly windings as %s good windings", len(good_windings))
|
3119
3066
|
logger.debug("end of collect_windings")
|
3120
3067
|
return good_windings
|
3121
3068
|
|
3122
|
-
def search_stator_subregions(self,
|
3069
|
+
def search_stator_subregions(self,
|
3070
|
+
startangle,
|
3071
|
+
endangle,
|
3072
|
+
single=False):
|
3123
3073
|
logger.debug("Begin of search_stator_subregions")
|
3124
3074
|
|
3125
|
-
if place == 'in':
|
3126
|
-
self.is_inner = True
|
3127
|
-
elif place == 'out':
|
3128
|
-
self.is_inner = False
|
3129
|
-
|
3130
3075
|
if self.alfa == 0.0:
|
3131
3076
|
self.alfa = np.pi * 2.0
|
3132
3077
|
|
@@ -3141,18 +3086,20 @@ class Geometry(object):
|
|
3141
3086
|
self.max_radius)
|
3142
3087
|
|
3143
3088
|
windings = self.collect_windings()
|
3144
|
-
[a.set_type(
|
3089
|
+
[a.set_type(AREA.TYPE_AIR) for a in self.list_of_areas()
|
3090
|
+
if a.is_type(AREA.TYPE_WINDINGS_OR_AIR)]
|
3145
3091
|
windings_found = len(windings)
|
3146
3092
|
logger.debug("%d windings found", windings_found)
|
3093
|
+
self.has_windings = windings_found > 0
|
3147
3094
|
|
3148
3095
|
if windings_found > 1:
|
3149
3096
|
windings_surface = [[w.surface, w] for w in windings]
|
3150
3097
|
windings_surface.sort(reverse=True)
|
3151
|
-
max_size = windings_surface[0]
|
3152
|
-
for sz, w in windings_surface:
|
3098
|
+
max_size, max_w = windings_surface[0]
|
3099
|
+
for sz, w in windings_surface[1:]:
|
3153
3100
|
logger.debug("winding size = %s", sz)
|
3154
|
-
if sz / max_size < 0.
|
3155
|
-
w.set_type(
|
3101
|
+
if sz / max_size < 0.80:
|
3102
|
+
w.set_type(AREA.TYPE_AIR)
|
3156
3103
|
if sz / max_size < 0.2:
|
3157
3104
|
windings_found -= 1
|
3158
3105
|
windings = [a for a in self.list_of_areas()
|
@@ -3160,8 +3107,9 @@ class Geometry(object):
|
|
3160
3107
|
if windings_found > 2 and len(windings) == 1:
|
3161
3108
|
logger.info("no windings remaining")
|
3162
3109
|
# no windings
|
3163
|
-
[w.set_type(
|
3164
|
-
[a.set_type(
|
3110
|
+
[w.set_type(AREA.TYPE_AIR) for w in windings]
|
3111
|
+
[a.set_type(AREA.TYPE_IRON) for a in self.list_of_areas()
|
3112
|
+
if a.is_iron()]
|
3165
3113
|
windings = []
|
3166
3114
|
elif len(windings) < windings_found:
|
3167
3115
|
logger.info("%d windings remaining", len(windings))
|
@@ -3197,7 +3145,8 @@ class Geometry(object):
|
|
3197
3145
|
self.wdg_is_mirrored = False
|
3198
3146
|
|
3199
3147
|
# air or iron near windings and near airgap ?
|
3200
|
-
air_areas = [a for a in self.list_of_areas()
|
3148
|
+
air_areas = [a for a in self.list_of_areas()
|
3149
|
+
if a.is_type(AREA.TYPE_AIR_OR_IRON)]
|
3201
3150
|
for a in air_areas:
|
3202
3151
|
if a.around_windings(windings, self):
|
3203
3152
|
logger.debug("Area %s", a.identifier())
|
@@ -3211,7 +3160,7 @@ class Geometry(object):
|
|
3211
3160
|
if a.close_to_startangle:
|
3212
3161
|
if not wdg_close_to_startangle:
|
3213
3162
|
logger.debug("#0.1 ===> close to startangle")
|
3214
|
-
a.
|
3163
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3215
3164
|
continue
|
3216
3165
|
|
3217
3166
|
if a.close_to_endangle:
|
@@ -3219,10 +3168,10 @@ class Geometry(object):
|
|
3219
3168
|
logger.debug("#0.2 ===> close to endangle")
|
3220
3169
|
if(a.min_angle < wdg_min_angle and
|
3221
3170
|
a.close_to_ag):
|
3222
|
-
a.
|
3171
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3223
3172
|
continue
|
3224
3173
|
|
3225
|
-
a.
|
3174
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3226
3175
|
continue
|
3227
3176
|
|
3228
3177
|
if greater_equal(a.min_air_angle, wdg_min_angle):
|
@@ -3232,53 +3181,54 @@ class Geometry(object):
|
|
3232
3181
|
|
3233
3182
|
if a.close_to_endangle and self.is_mirrored():
|
3234
3183
|
logger.debug("#1 ===> endangle and mirrored <===")
|
3235
|
-
a.
|
3184
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3236
3185
|
elif less_equal(a.max_air_angle, wdg_max_angle):
|
3237
3186
|
logger.debug("#2 ===> %s <= %s <===",
|
3238
3187
|
a.max_air_angle,
|
3239
3188
|
wdg_max_angle)
|
3240
|
-
a.
|
3189
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3241
3190
|
else:
|
3242
3191
|
logger.debug("#3 ===> %s > %s <===",
|
3243
3192
|
a.max_air_angle,
|
3244
3193
|
wdg_max_angle)
|
3245
|
-
a.
|
3194
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3246
3195
|
else:
|
3247
3196
|
logger.debug("#4 ===> %s < %s <===",
|
3248
3197
|
a.min_air_angle,
|
3249
3198
|
wdg_min_angle)
|
3250
|
-
a.
|
3199
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3251
3200
|
else:
|
3252
3201
|
logger.debug("#5 not around windings")
|
3253
|
-
a.
|
3202
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3254
3203
|
|
3255
3204
|
# yoke or shaft ?
|
3256
|
-
iron_areas = [a for a in self.list_of_areas()
|
3205
|
+
iron_areas = [a for a in self.list_of_areas()
|
3206
|
+
if a.is_type(AREA.TYPE_YOKE)]
|
3257
3207
|
for a in iron_areas:
|
3258
3208
|
if a.around_windings(windings, self):
|
3259
3209
|
if less(a.min_dist, wdg_max_dist):
|
3260
3210
|
if less_equal(a.max_dist, wdg_max_dist):
|
3261
|
-
a.
|
3211
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3262
3212
|
else:
|
3263
3213
|
dist_low = wdg_max_dist - a.min_dist
|
3264
3214
|
dist_up = a.max_dist - wdg_max_dist
|
3265
3215
|
if dist_low > dist_up:
|
3266
|
-
a.
|
3216
|
+
a.set_type(AREA.TYPE_TOOTH) # iron shaft (Zahn)
|
3267
3217
|
|
3268
|
-
shaft_areas = [a for a in self.list_of_areas()
|
3218
|
+
shaft_areas = [a for a in self.list_of_areas()
|
3219
|
+
if a.is_type(AREA.TYPE_SHAFT)]
|
3269
3220
|
if shaft_areas:
|
3270
3221
|
if len(shaft_areas) > 1:
|
3271
|
-
logger.
|
3222
|
+
logger.debug("More than one shaft in stator ?!?")
|
3272
3223
|
return
|
3273
3224
|
self.check_shaft_area(shaft_areas[0])
|
3225
|
+
logger.debug("End of search_stator_subregions")
|
3274
3226
|
|
3275
|
-
def search_rotor_subregions(self,
|
3276
|
-
|
3277
|
-
|
3278
|
-
|
3279
|
-
|
3280
|
-
elif place == 'out':
|
3281
|
-
self.is_inner = False
|
3227
|
+
def search_rotor_subregions(self,
|
3228
|
+
startangle,
|
3229
|
+
endangle,
|
3230
|
+
single=False):
|
3231
|
+
logger.debug("Begin of search_rotor_subregions")
|
3282
3232
|
|
3283
3233
|
if self.alfa == 0.0:
|
3284
3234
|
self.alfa = np.pi * 2.0
|
@@ -3290,20 +3240,65 @@ class Geometry(object):
|
|
3290
3240
|
self.alfa,
|
3291
3241
|
self.center,
|
3292
3242
|
self.min_radius,
|
3293
|
-
self.max_radius
|
3243
|
+
self.max_radius,
|
3244
|
+
startangle,
|
3245
|
+
endangle)
|
3294
3246
|
if t in types:
|
3295
3247
|
types[t] += 1
|
3296
3248
|
else:
|
3297
3249
|
types[t] = 1
|
3298
3250
|
|
3299
|
-
if
|
3251
|
+
if AREA.TYPE_SHAFT in types:
|
3300
3252
|
logger.debug("Shaft is available")
|
3301
3253
|
|
3302
|
-
if
|
3303
|
-
if types
|
3304
|
-
|
3254
|
+
if AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP in types: # magnet rectangle near ag
|
3255
|
+
if AREA.TYPE_MAGNET_RECT in types: # magnet rectangle
|
3256
|
+
mag_rectangles = [a for a in self.list_of_areas()
|
3257
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3258
|
+
for a in mag_rectangles:
|
3259
|
+
if self.is_inner:
|
3260
|
+
dist_1 = a.max_dist + 0.5
|
3261
|
+
dist_2 = self.max_radius + 5
|
3262
|
+
else:
|
3263
|
+
dist_1 = a_min_dist - 0.5
|
3264
|
+
dist_2 = self.min_radius - 5
|
3265
|
+
|
3266
|
+
mid_angle = a.get_mid_angle(self.center)
|
3267
|
+
p1 = point(self.center, dist_1, mid_angle)
|
3268
|
+
p2 = point(self.center, dist_2, mid_angle)
|
3269
|
+
line = Line(Element(start=p1, end=p2))
|
3270
|
+
logger.debug("magnet intersect line: %s to %s", p1, p2)
|
3271
|
+
pts = self.split_and_get_intersect_points(line,
|
3272
|
+
aktion=False,
|
3273
|
+
include_end=False)
|
3274
|
+
logger.debug("magnet intersect points: %s", pts)
|
3275
|
+
if not pts:
|
3276
|
+
a.set_type(AREA.TYPE_MAGNET_UNDEFINED)
|
3277
|
+
mag_rectangles = [a for a in self.list_of_areas()
|
3278
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3279
|
+
if mag_rectangles: # undo
|
3280
|
+
logger.debug("--- undo ---")
|
3281
|
+
[a.set_type(AREA.TYPE_MAGNET_RECT) for a in self.list_of_areas()
|
3282
|
+
if a.is_type(AREA.TYPE_MAGNET_UNDEFINED)]
|
3283
|
+
else:
|
3284
|
+
logger.debug("--- set type 3 ---")
|
3285
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3286
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP)]
|
3287
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3288
|
+
if a.is_type(AREA.TYPE_MAGNET_UNDEFINED)]
|
3289
|
+
types.pop(AREA.TYPE_MAGNET_RECT)
|
3290
|
+
else:
|
3291
|
+
# set magnet
|
3292
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in self.list_of_areas()
|
3293
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP)]
|
3294
|
+
types[AREA.TYPE_MAGNET_RECT_NEAR_AIRGAP] = 0
|
3295
|
+
|
3296
|
+
if AREA.TYPE_MAGNET_RECT in types: # magnet rectangle
|
3297
|
+
if types[AREA.TYPE_MAGNET_RECT] > 1:
|
3298
|
+
logger.debug("%s embedded magnets in rotor",
|
3299
|
+
types[AREA.TYPE_MAGNET_RECT])
|
3305
3300
|
emb_mag_areas = [a for a in self.list_of_areas()
|
3306
|
-
if a.
|
3301
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3307
3302
|
[a.set_surface(self.is_mirrored()) for a in emb_mag_areas]
|
3308
3303
|
max_surface = 0.0
|
3309
3304
|
max_phi = 0.0
|
@@ -3315,30 +3310,34 @@ class Geometry(object):
|
|
3315
3310
|
for a in emb_mag_areas:
|
3316
3311
|
if a.surface < max_surface * 0.20: # too small
|
3317
3312
|
logger.debug(
|
3318
|
-
"embedded magnet too small: convert to air"
|
3313
|
+
"embedded magnet %s too small: convert to air",
|
3314
|
+
a.identifier())
|
3319
3315
|
logger.debug("max surface : %s", max_surface)
|
3320
3316
|
logger.debug("area surface: %s", a.surface)
|
3321
3317
|
logger.debug("max phi : %s", max_phi)
|
3322
3318
|
logger.debug("area phi : %s", a.phi)
|
3323
3319
|
if not np.isclose(a.phi, max_phi):
|
3324
|
-
a.set_type(
|
3320
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3325
3321
|
|
3326
3322
|
# set iron
|
3327
|
-
[a.set_type(
|
3323
|
+
[a.set_type(AREA.TYPE_IRON) for a in self.list_of_areas()
|
3324
|
+
if a.is_type(AREA.TYPE_MAGNET_AIRGAP)]
|
3328
3325
|
|
3329
|
-
iron_mag_areas = [a for a in self.list_of_areas()
|
3330
|
-
|
3326
|
+
iron_mag_areas = [a for a in self.list_of_areas()
|
3327
|
+
if a.is_type(AREA.TYPE_MAGNET_OR_IRON)]
|
3328
|
+
air_mag_areas = [a for a in self.list_of_areas()
|
3329
|
+
if a.is_type(AREA.TYPE_MAGNET_OR_AIR)]
|
3331
3330
|
ag_areas = [a for a in self.list_of_areas() if a.close_to_ag]
|
3332
3331
|
if len(ag_areas) == 1:
|
3333
3332
|
if len(iron_mag_areas) == 1:
|
3334
|
-
[a.set_type(
|
3333
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in iron_mag_areas]
|
3335
3334
|
iron_mag_areas = []
|
3336
3335
|
if len(air_mag_areas) == 1:
|
3337
|
-
[a.set_type(
|
3336
|
+
[a.set_type(AREA.TYPE_MAGNET_AIRGAP) for a in air_mag_areas]
|
3338
3337
|
air_mag_areas = []
|
3339
3338
|
|
3340
|
-
[a.set_type(
|
3341
|
-
[a.set_type(
|
3339
|
+
[a.set_type(AREA.TYPE_IRON) for a in iron_mag_areas]
|
3340
|
+
[a.set_type(AREA.TYPE_AIR) for a in air_mag_areas]
|
3342
3341
|
|
3343
3342
|
if self.is_mirrored():
|
3344
3343
|
mid_alfa = round(self.alfa, 3)
|
@@ -3348,44 +3347,64 @@ class Geometry(object):
|
|
3348
3347
|
mag_areas = [[abs(round(a.phi, 3) - mid_alfa),
|
3349
3348
|
a.id,
|
3350
3349
|
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]
|
3350
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3351
|
+
|
3352
|
+
shaft_areas = [a for a in self.list_of_areas()
|
3353
|
+
if a.is_type(AREA.TYPE_SHAFT)]
|
3382
3354
|
if shaft_areas:
|
3383
3355
|
if len(shaft_areas) > 1:
|
3384
|
-
logger.
|
3356
|
+
logger.debug("More than one shaft in rotor ?!?")
|
3385
3357
|
return
|
3386
3358
|
self.check_shaft_area(shaft_areas[0])
|
3387
3359
|
|
3388
|
-
|
3360
|
+
magnets = [a for a in self.list_of_areas()
|
3361
|
+
if a.is_magnet()]
|
3362
|
+
self.has_magnets = len(magnets) > 0
|
3363
|
+
for m in magnets:
|
3364
|
+
m.phi = m.get_magnet_orientation()
|
3365
|
+
logger.debug("%s magnets found in rotor", len(magnets))
|
3366
|
+
|
3367
|
+
if not single:
|
3368
|
+
if not magnets:
|
3369
|
+
[a.set_type(AREA.TYPE_AIR) for a in self.list_of_areas()]
|
3370
|
+
self.search_stator_subregions(startangle, endangle, single=single)
|
3371
|
+
return
|
3372
|
+
|
3373
|
+
logger.debug("end of search_rotor_subregions")
|
3374
|
+
|
3375
|
+
def recalculate_magnet_orientation(self):
|
3376
|
+
logger.debug("begin of recalculate_magnet_orientation")
|
3377
|
+
magnet_areas = [a for a in self.list_of_areas()
|
3378
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3379
|
+
self.recalculate_magnet_group(magnet_areas)
|
3380
|
+
|
3381
|
+
magnet_areas = [a for a in self.list_of_areas()
|
3382
|
+
if a.is_type(AREA.TYPE_MAGNET_AIRGAP)]
|
3383
|
+
for a in magnet_areas:
|
3384
|
+
a.phi = a.get_magnet_orientation()
|
3385
|
+
logger.debug("end of recalculate_magnet_orientation")
|
3386
|
+
|
3387
|
+
def recalculate_magnet_group(self, areas):
|
3388
|
+
if not areas:
|
3389
|
+
return
|
3390
|
+
elements = []
|
3391
|
+
for a in areas:
|
3392
|
+
elements += a.elements()
|
3393
|
+
geom = Geometry(elements, center=self.center)
|
3394
|
+
builder = AreaBuilder(geom=geom)
|
3395
|
+
if builder.create_area_groups(areas):
|
3396
|
+
return # bad
|
3397
|
+
group_list = builder.area_list
|
3398
|
+
# for debugging
|
3399
|
+
# self.areagroup_list = group_list
|
3400
|
+
for group in group_list:
|
3401
|
+
if not group.is_magnet_rectangle():
|
3402
|
+
logger.debug("Warning: group is not a rectangle")
|
3403
|
+
group.set_type(AREA.TYPE_MAGNET_RECT)
|
3404
|
+
phi = group.get_magnet_orientation()
|
3405
|
+
for a in group.areas_of_group:
|
3406
|
+
logger.debug("Replace phi %s by %s", a.phi, phi)
|
3407
|
+
a.phi = phi
|
3389
3408
|
|
3390
3409
|
def search_unknown_subregions(self):
|
3391
3410
|
logger.debug("begin of search_unknown_subregions")
|
@@ -3401,22 +3420,31 @@ class Geometry(object):
|
|
3401
3420
|
else:
|
3402
3421
|
types[t] = 1
|
3403
3422
|
|
3404
|
-
if
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3423
|
+
if types.get(AREA.TYPE_MAGNET_RECT, 0) > 1:
|
3424
|
+
logger.debug("%s embedded magnets in rotor",
|
3425
|
+
types[AREA.TYPE_MAGNET_RECT])
|
3426
|
+
emb_mag_areas = [a for a in self.list_of_areas()
|
3427
|
+
if a.is_type(AREA.TYPE_MAGNET_RECT)]
|
3428
|
+
[a.set_surface(self.is_mirrored()) for a in emb_mag_areas]
|
3429
|
+
max_surface = 0.0
|
3430
|
+
for a in emb_mag_areas:
|
3431
|
+
max_surface = max(max_surface, a.surface)
|
3413
3432
|
|
3414
|
-
|
3415
|
-
|
3416
|
-
|
3433
|
+
for a in emb_mag_areas:
|
3434
|
+
if a.surface < max_surface * 0.20: # too small
|
3435
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3417
3436
|
|
3418
3437
|
logger.debug("end of search_unknown_subregions")
|
3419
3438
|
|
3439
|
+
def magnets_in_the_middle(self, midangle):
|
3440
|
+
mag_areas = [a for a in self.list_of_areas()
|
3441
|
+
if a.is_magnet()]
|
3442
|
+
logger.debug("%s magnets in geom", len(mag_areas))
|
3443
|
+
for a in mag_areas:
|
3444
|
+
if a.max_angle > midangle and a.min_angle < midangle:
|
3445
|
+
return True
|
3446
|
+
return False
|
3447
|
+
|
3420
3448
|
def looking_for_corners(self):
|
3421
3449
|
if self.is_inner:
|
3422
3450
|
logger.debug("looking_for_corners: inner")
|
@@ -3434,14 +3462,14 @@ class Geometry(object):
|
|
3434
3462
|
|
3435
3463
|
def num_areas_of_type(self, type):
|
3436
3464
|
return len([area for area in self.list_of_areas()
|
3437
|
-
if area.type
|
3465
|
+
if area.is_type(type)])
|
3438
3466
|
|
3439
3467
|
def num_of_windings(self):
|
3440
|
-
return self.num_areas_of_type(
|
3468
|
+
return self.num_areas_of_type(AREA.TYPE_WINDINGS)
|
3441
3469
|
|
3442
3470
|
def area_close_to_endangle(self, type):
|
3443
3471
|
return len([area for area in self.list_of_areas()
|
3444
|
-
if area.type
|
3472
|
+
if area.is_type(type) and area.close_to_endangle])
|
3445
3473
|
|
3446
3474
|
def corners_dont_match(self):
|
3447
3475
|
if self.is_mirrored():
|
@@ -3460,7 +3488,7 @@ class Geometry(object):
|
|
3460
3488
|
return True
|
3461
3489
|
return False
|
3462
3490
|
|
3463
|
-
def
|
3491
|
+
def get_appendices(self):
|
3464
3492
|
c = 0
|
3465
3493
|
end_nodes = []
|
3466
3494
|
for n in self.g.nodes():
|
@@ -3473,154 +3501,202 @@ class Geometry(object):
|
|
3473
3501
|
|
3474
3502
|
if not is_Circle(el):
|
3475
3503
|
end_nodes.append((n, nbrs[0], el))
|
3504
|
+
return end_nodes
|
3505
|
+
|
3506
|
+
def connect_all_nodes(self,
|
3507
|
+
additional_nodes=[],
|
3508
|
+
rtol=1e-04, atol=1e-04,
|
3509
|
+
main=False):
|
3510
|
+
logger.debug("begin of connect_all_nodes")
|
3511
|
+
timer = Timer(start_it=True)
|
3512
|
+
nodes_list = self.get_nodes()
|
3513
|
+
c1 = 0
|
3514
|
+
c2 = 0
|
3515
|
+
additional_nodes_list = []
|
3516
|
+
for n in additional_nodes:
|
3517
|
+
if not n in nodes_list:
|
3518
|
+
additional_nodes_list.append(n)
|
3519
|
+
c1 += 1
|
3520
|
+
else:
|
3521
|
+
c2 += 1
|
3522
|
+
logger.debug("connect_all_nodes: %s added, %s already available", c1, c2)
|
3523
|
+
|
3524
|
+
corr = self.connect_nodes(nodes_list,
|
3525
|
+
rtol=rtol, atol=atol)
|
3526
|
+
if additional_nodes_list:
|
3527
|
+
corr += self.connect_nodes(additional_nodes_list,
|
3528
|
+
omit_single_element=True,
|
3529
|
+
rtol=rtol, atol=atol)
|
3530
|
+
t = timer.stop("-- {} connections in %0.4f seconds --".format(corr))
|
3531
|
+
if main:
|
3532
|
+
self.journal.put_nodes_connected(corr)
|
3533
|
+
self.journal.put('time_node_connections', t)
|
3534
|
+
logger.debug("==> %s nodes connected", corr)
|
3535
|
+
logger.debug("end of connect_all_nodes")
|
3536
|
+
return corr
|
3537
|
+
|
3538
|
+
def connect_nodes(self, nodes_list,
|
3539
|
+
rtol=1e-03, atol=1e-03,
|
3540
|
+
omit_single_element=False,
|
3541
|
+
ignore_end=False):
|
3542
|
+
logger.debug("begin of connect_nodes(rtol=%s, atol=%s)", rtol, atol)
|
3543
|
+
logger.debug("-- %s nodes exist", len(nodes_list))
|
3476
3544
|
|
3477
|
-
|
3478
|
-
|
3479
|
-
if self.node_connected(
|
3480
|
-
|
3545
|
+
count = 0
|
3546
|
+
for n in nodes_list:
|
3547
|
+
if self.node_connected(n,
|
3548
|
+
rtol=rtol, atol=atol,
|
3549
|
+
omit_single_element=omit_single_element,
|
3550
|
+
ignore_end=ignore_end):
|
3551
|
+
count += 1
|
3552
|
+
|
3553
|
+
logger.debug("end of connect_nodes => %s", count)
|
3554
|
+
return count
|
3555
|
+
|
3556
|
+
def connect_all_appendices(self, rtol=1e-04, atol=1e-04, main=False):
|
3557
|
+
logger.debug("begin of connect_all_appendices")
|
3558
|
+
timer = Timer(start_it=True)
|
3559
|
+
appendix_list = self.get_appendices()
|
3560
|
+
before = len(appendix_list)
|
3561
|
+
if main:
|
3562
|
+
self.journal.put_appendices(len(appendix_list))
|
3563
|
+
corr = self.connect_appendices(appendix_list, rtol=rtol, atol=atol)
|
3564
|
+
corr_total = corr
|
3565
|
+
|
3566
|
+
if corr < before:
|
3567
|
+
appendix_list = self.get_appendices()
|
3568
|
+
before = len(appendix_list)
|
3569
|
+
corr = self.connect_appendices(appendix_list, rtol=rtol, atol=atol)
|
3570
|
+
corr_total += corr
|
3571
|
+
t = timer.stop("-- {} connections in %0.4f seconds --".format(corr))
|
3572
|
+
if main:
|
3573
|
+
self.journal.put_appendices_connected(corr_total)
|
3574
|
+
self.journal.put('time_app_connections', t)
|
3575
|
+
|
3576
|
+
logger.debug("==> %s appendices connected", corr_total)
|
3577
|
+
logger.debug("end of connect_all_appendices")
|
3578
|
+
return corr_total
|
3579
|
+
|
3580
|
+
def connect_appendices(self, appendix_list, rtol=1e-03, atol=1e-03, ignore_end=False):
|
3581
|
+
logger.debug("begin of connect_appendices(rtol=%s, atol=%s)", rtol, atol)
|
3582
|
+
logger.debug("-- %s appendices exist", len(appendix_list))
|
3583
|
+
self.fixed_appendices = []
|
3584
|
+
|
3585
|
+
count = 0
|
3586
|
+
for n0, n1, el in appendix_list:
|
3587
|
+
logger.debug("Appendix Node at %s", n0)
|
3588
|
+
if n0 in self.fixed_appendices:
|
3589
|
+
logger.debug(" - Node already fixed")
|
3481
3590
|
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
|
3591
|
+
count += self.connect_appendix(n0, n1, el,
|
3592
|
+
rtol=rtol, atol=atol,
|
3593
|
+
ignore_end=ignore_end)
|
3492
3594
|
|
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]))
|
3595
|
+
self.fixed_appendices = []
|
3500
3596
|
|
3501
|
-
|
3502
|
-
|
3503
|
-
c += self.remove_appendix(n0, n1)
|
3504
|
-
return c
|
3597
|
+
logger.debug("end of connect_appendices => %s", count)
|
3598
|
+
return count
|
3505
3599
|
|
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")
|
3600
|
+
def connect_appendix(self, n0, n1, el, rtol=1e-03, atol=1e-03, ignore_end=False):
|
3601
|
+
logger.debug("begin of connect_appendix(%s, rtol=%s, atol=%s)", n0, rtol, atol)
|
3521
3602
|
|
3522
|
-
|
3523
|
-
|
3524
|
-
|
3525
|
-
|
3526
|
-
|
3603
|
+
if points_are_close(n0, n1, rtol=1e-04, atol=1e-04):
|
3604
|
+
# a very tiny appendix
|
3605
|
+
d = distance(n0, n1)
|
3606
|
+
if less(d, 0.001):
|
3607
|
+
logger.debug("-- WARNING: a very tiny appendix of length %s", d)
|
3608
|
+
nbr_list = [nbr for nbr in self.g.neighbors(n1)
|
3609
|
+
if not nodes_are_equal(nbr, n0)]
|
3527
3610
|
|
3528
|
-
|
3529
|
-
|
3530
|
-
|
3611
|
+
if len(nbr_list) == 0:
|
3612
|
+
logger.debug("end of connect_appendix: => lonesome appendix -> no action")
|
3613
|
+
return 0
|
3531
3614
|
|
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])
|
3615
|
+
logger.debug(" remove it")
|
3616
|
+
self._remove_edge(n0, n1)
|
3617
|
+
return 1
|
3546
3618
|
|
3547
|
-
|
3548
|
-
|
3619
|
+
if self.node_connected(n0, rtol=rtol, atol=atol, ignore_end=ignore_end):
|
3620
|
+
logger.debug("end of connect_appendix: %s CONNECTED", n0)
|
3621
|
+
return 1
|
3549
3622
|
|
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
|
3623
|
+
nn = self.find_other_node(n0)
|
3624
|
+
if not nn:
|
3625
|
+
logger.debug("end of connect_appendix: => No node found nearby")
|
3626
|
+
return 0
|
3571
3627
|
|
3572
|
-
|
3573
|
-
|
3574
|
-
|
3575
|
-
|
3576
|
-
|
3577
|
-
self.
|
3578
|
-
|
3579
|
-
|
3628
|
+
logger.debug("Node %s is near %s", n0, nn)
|
3629
|
+
logger.debug(" -- appendix %s from %s to %s", el.classname(), n0, n1)
|
3630
|
+
try:
|
3631
|
+
logger.debug("remove edge of %s from %s to %s",
|
3632
|
+
el.classname(), el.p1, el.p2)
|
3633
|
+
self._remove_edge(n0, n1)
|
3634
|
+
except Exception:
|
3635
|
+
f = Path(__file__)
|
3636
|
+
msg = "{} #{}: delete of {} - {} failed".format(
|
3637
|
+
f.name, lineno(),
|
3638
|
+
n0, n1)
|
3639
|
+
self.journal.put_warning(msg)
|
3640
|
+
logger.warning("WARNING: %s", msg)
|
3641
|
+
logger.debug("-- Element %s", el)
|
3642
|
+
|
3643
|
+
self.add_or_join_edge(nn, n1, el,
|
3644
|
+
rtol=rtol,
|
3645
|
+
atol=atol)
|
3646
|
+
self.fixed_appendices.append(nn)
|
3647
|
+
logger.debug("end of connect_appendix: connected")
|
3648
|
+
return 1
|
3580
3649
|
|
3581
|
-
def
|
3582
|
-
|
3583
|
-
|
3584
|
-
|
3650
|
+
def delete_appendices(self, appendix_list):
|
3651
|
+
c = 0
|
3652
|
+
for n0, n1, e in appendix_list:
|
3653
|
+
logger.debug("Deadend Node at %s", n0)
|
3654
|
+
c += self.remove_appendix(n0, n1)
|
3655
|
+
return c
|
3585
3656
|
|
3586
|
-
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3590
|
-
|
3591
|
-
|
3592
|
-
|
3657
|
+
def delete_all_appendices(self):
|
3658
|
+
logger.debug("begin of delete_all_appendices")
|
3659
|
+
appendix_list = self.get_appendices()
|
3660
|
+
app = len(appendix_list)
|
3661
|
+
if not app:
|
3662
|
+
logger.debug("end of delete_all_appendices: no appendices")
|
3663
|
+
return
|
3593
3664
|
|
3594
|
-
|
3595
|
-
|
3665
|
+
corr = self.delete_appendices(appendix_list)
|
3666
|
+
self.journal.put_appendices_deleted(corr)
|
3667
|
+
|
3668
|
+
logger.debug("==> %s appendices removed", corr)
|
3669
|
+
logger.debug("end of delete_all_appendices")
|
3596
3670
|
|
3597
|
-
def connect_arc_or_line(self, n, el, n1, n2,
|
3598
|
-
elements = el.split([n], rtol=
|
3671
|
+
def connect_arc_or_line(self, n, el, n1, n2, rtol=1e-03, atol=1e-03, mdec=0):
|
3672
|
+
elements = el.split([n], rtol=rtol, atol=atol, mdec=mdec)
|
3599
3673
|
if len(elements) != 2:
|
3600
|
-
logger.
|
3601
|
-
logger.
|
3674
|
+
logger.warning("Not 2 Elements")
|
3675
|
+
logger.warning("split(rtol=%s, atol=%s, mdec=%s)", rtol, atol, mdec)
|
3676
|
+
logger.warning("Node {} in Element {}".format(n, el))
|
3602
3677
|
for e in elements:
|
3603
3678
|
logger.info(e)
|
3604
3679
|
assert(len(elements) == 2)
|
3605
3680
|
|
3606
3681
|
logger.debug("HIT! Node %s is in %s", n, el)
|
3607
|
-
logger.debug(" => remove
|
3682
|
+
logger.debug(" => remove %s", el)
|
3683
|
+
self.fixed_appendices.append(n1)
|
3684
|
+
self.fixed_appendices.append(n2)
|
3608
3685
|
self._remove_edge(n1, n2)
|
3609
3686
|
|
3610
3687
|
for element in elements:
|
3611
3688
|
logger.debug("Split: %s", element)
|
3612
3689
|
|
3613
|
-
rtol = tol
|
3614
|
-
atol = tol
|
3615
|
-
|
3616
3690
|
for element in elements:
|
3617
3691
|
n1_inside = element.is_point_inside(n1,
|
3618
3692
|
rtol=rtol,
|
3619
3693
|
atol=atol,
|
3694
|
+
mdec=mdec,
|
3620
3695
|
include_end=True)
|
3621
3696
|
n2_inside = element.is_point_inside(n2,
|
3622
3697
|
rtol=rtol,
|
3623
3698
|
atol=atol,
|
3699
|
+
mdec=mdec,
|
3624
3700
|
include_end=True)
|
3625
3701
|
if n1_inside and n2_inside:
|
3626
3702
|
logger.error("FATAL: both inside %s", element)
|
@@ -3629,37 +3705,63 @@ class Geometry(object):
|
|
3629
3705
|
else:
|
3630
3706
|
if n1_inside:
|
3631
3707
|
logger.debug(" <= #1 add from %s to %s", n1, n)
|
3632
|
-
self.
|
3708
|
+
self.add_element(element,
|
3709
|
+
rtol=self.rtol,
|
3710
|
+
atol=self.atol)
|
3633
3711
|
else:
|
3634
3712
|
logger.debug(" <= #2 add from %s to %s", n2, n)
|
3635
|
-
self.
|
3713
|
+
self.add_element(element,
|
3714
|
+
rtol=self.rtol,
|
3715
|
+
atol=self.atol)
|
3636
3716
|
|
3637
|
-
def connect_circle(self, n, el, n1, n2,
|
3638
|
-
elements = el.split([n], rtol=
|
3717
|
+
def connect_circle(self, n, el, n1, n2, rtol=1e-03, atol=1e-03):
|
3718
|
+
elements = el.split([n], rtol=rtol, atol=atol)
|
3639
3719
|
assert(len(elements) == 3)
|
3640
3720
|
|
3641
|
-
logger.debug("Node %s is in %s", n, el)
|
3642
|
-
logger.debug(" => remove from %s to %s", n1, n2)
|
3721
|
+
logger.debug("connect_circle: Node %s is in %s", n, el)
|
3722
|
+
logger.debug(" => remove %s from %s to %s", el.classname(), n1, n2)
|
3723
|
+
e = self.get_edge_element(n1, n2)
|
3724
|
+
if not e:
|
3725
|
+
logger.error("Element from %s to %s not found", n1, n2)
|
3726
|
+
else:
|
3727
|
+
logger.debug("Element to Remove: %s", e)
|
3643
3728
|
self._remove_edge(n1, n2)
|
3729
|
+
|
3644
3730
|
for element in elements:
|
3645
|
-
|
3646
|
-
|
3731
|
+
self.add_element(element,
|
3732
|
+
rtol=self.rtol,
|
3733
|
+
atol=self.atol)
|
3734
|
+
|
3735
|
+
def node_connected(self, n,
|
3736
|
+
rtol=1e-03, atol=1e-03,
|
3737
|
+
omit_single_element=False,
|
3738
|
+
ignore_end=False):
|
3739
|
+
mdec = 2
|
3740
|
+
count = 0
|
3741
|
+
el_list = []
|
3742
|
+
for n1, n2, el in self.elements_and_nodes(Shape):
|
3743
|
+
if not el.is_near(n):
|
3744
|
+
#logger.debug("Node %s is NOT near this edge", n)
|
3745
|
+
continue
|
3746
|
+
elif el.is_point_inside(n,
|
3747
|
+
rtol=rtol,
|
3748
|
+
atol=atol,
|
3749
|
+
mdec=mdec,
|
3750
|
+
include_end=False,
|
3751
|
+
ignore_end=ignore_end):
|
3752
|
+
logger.debug("Node %s is inside of an edge", n)
|
3753
|
+
el_list.append((n1, n2, el))
|
3647
3754
|
|
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
|
3755
|
+
if omit_single_element and len(el_list) < 2:
|
3756
|
+
return 0
|
3757
|
+
|
3758
|
+
for n1, n2, el in el_list:
|
3759
|
+
if is_Circle(el):
|
3760
|
+
self.connect_circle(n, el, n1, n2, rtol=rtol, atol=atol)
|
3761
|
+
else:
|
3762
|
+
self.connect_arc_or_line(n, el, n1, n2, rtol=rtol, atol=atol, mdec=mdec)
|
3763
|
+
count += 1
|
3764
|
+
return count
|
3663
3765
|
|
3664
3766
|
def remove_appendix(self, n1, n2, incr_text=''):
|
3665
3767
|
e_dict = self.g.get_edge_data(n1, n2)
|
@@ -3677,12 +3779,21 @@ class Geometry(object):
|
|
3677
3779
|
logger.debug("%s remove_appendix(%s, %s)", incr_text, n1, n2)
|
3678
3780
|
self._remove_edge(n1, n2)
|
3679
3781
|
c = 1
|
3680
|
-
|
3782
|
+
try:
|
3783
|
+
nbrs = [nbr for nbr in self.g.neighbors(n2)]
|
3784
|
+
except nx.NetworkXError:
|
3785
|
+
logger.debug("Node %s already deleted", n2)
|
3786
|
+
nbrs = []
|
3787
|
+
|
3681
3788
|
if len(nbrs) == 1:
|
3682
3789
|
c += self.remove_appendix(n2, nbrs[0], incr_text + '.')
|
3683
3790
|
return c
|
3684
3791
|
|
3685
|
-
def
|
3792
|
+
def adjust_all_points(self):
|
3793
|
+
for e in self.elements():
|
3794
|
+
e.adjust_points()
|
3795
|
+
|
3796
|
+
def split_and_get_intersect_points(self, el, aktion=True, include_end=True):
|
3686
3797
|
logger.debug("begin of split_and_get_intersect_points")
|
3687
3798
|
rtol = 1e-03
|
3688
3799
|
atol = 1e-03
|
@@ -3691,12 +3802,15 @@ class Geometry(object):
|
|
3691
3802
|
pts = e.intersect_shape(el,
|
3692
3803
|
rtol=rtol,
|
3693
3804
|
atol=atol,
|
3694
|
-
include_end=
|
3805
|
+
include_end=include_end)
|
3695
3806
|
if pts:
|
3807
|
+
logger.debug("Split %s", e)
|
3808
|
+
[logger.debug("-- intersect point %s", p) for p in pts]
|
3696
3809
|
pts_inside = []
|
3697
3810
|
pts_real = []
|
3698
3811
|
for p in pts:
|
3699
|
-
|
3812
|
+
incl_end = is_Circle(e)
|
3813
|
+
if not e.is_point_inside(p, rtol, atol, include_end=incl_end):
|
3700
3814
|
# get the real point
|
3701
3815
|
n = self.find_the_node(p)
|
3702
3816
|
if n:
|
@@ -3723,7 +3837,9 @@ class Geometry(object):
|
|
3723
3837
|
logger.debug(
|
3724
3838
|
"=== OMIT ELEMENT WITH SAME NODES ===")
|
3725
3839
|
else:
|
3726
|
-
self.
|
3840
|
+
self.add_or_join_edge(n[0], n[1], e,
|
3841
|
+
rtol=rtol,
|
3842
|
+
atol=atol)
|
3727
3843
|
points += pts_real
|
3728
3844
|
|
3729
3845
|
logger.debug("end of split_and_get_intersect_points")
|
@@ -3737,6 +3853,30 @@ class Geometry(object):
|
|
3737
3853
|
return True
|
3738
3854
|
return False
|
3739
3855
|
|
3856
|
+
def _line_inside_magnets(self, p1, p2):
|
3857
|
+
for area in self.list_of_areas():
|
3858
|
+
if area.is_magnet():
|
3859
|
+
if area.is_point_inside(p1):
|
3860
|
+
if area.is_point_inside(p2):
|
3861
|
+
return True
|
3862
|
+
return False
|
3863
|
+
|
3864
|
+
def _line_inside_air(self, p1, p2):
|
3865
|
+
for area in self.list_of_areas():
|
3866
|
+
if area.is_air():
|
3867
|
+
if area.is_point_inside(p1):
|
3868
|
+
if area.is_point_inside(p2):
|
3869
|
+
return True
|
3870
|
+
return False
|
3871
|
+
|
3872
|
+
def _line_inside_not_iron(self, p1, p2):
|
3873
|
+
for area in self.list_of_areas():
|
3874
|
+
if area.is_shaft() or area.is_air() or area.is_magnet():
|
3875
|
+
if area.is_point_inside(p1):
|
3876
|
+
if area.is_point_inside(p2):
|
3877
|
+
return True
|
3878
|
+
return False
|
3879
|
+
|
3740
3880
|
def inside_area_list(self, p):
|
3741
3881
|
for area in self.list_of_areas():
|
3742
3882
|
if area.is_point_inside(p):
|
@@ -3749,7 +3889,7 @@ class Geometry(object):
|
|
3749
3889
|
d = distance(self.center, p)
|
3750
3890
|
logger.debug("-- p = %s, dist = %s", p, d)
|
3751
3891
|
for a in self.inside_area_list(p):
|
3752
|
-
logger.debug("-- Area type = %s", a.
|
3892
|
+
logger.debug("-- Area type = %s", a.legend())
|
3753
3893
|
logger.debug(" min=%s, max= %s", a.min_dist, a.max_dist)
|
3754
3894
|
logger.debug(" close to start = %s", a.close_to_startangle)
|
3755
3895
|
logger.debug(" close to end = %s", a.close_to_endangle)
|
@@ -3775,17 +3915,47 @@ class Geometry(object):
|
|
3775
3915
|
p1 = p2
|
3776
3916
|
continue
|
3777
3917
|
|
3778
|
-
n = self.find_nodes(p1, p2)
|
3779
3918
|
line = Line(Element(start=p1, end=p2),
|
3780
3919
|
color='darkred',
|
3781
3920
|
linestyle='dotted')
|
3782
|
-
self.
|
3783
|
-
|
3921
|
+
self.add_element(line,
|
3922
|
+
rtol=self.rtol,
|
3923
|
+
atol=self.atol)
|
3924
|
+
logger.debug("add line(%s)", line)
|
3784
3925
|
created = True
|
3785
3926
|
p1 = p2
|
3786
3927
|
|
3787
3928
|
return created
|
3788
3929
|
|
3930
|
+
def create_lines_outside_magnets(self, points):
|
3931
|
+
logger.debug("begin of create_lines_outside_magnets")
|
3932
|
+
if not points:
|
3933
|
+
return False
|
3934
|
+
created = False
|
3935
|
+
|
3936
|
+
p1 = points[0]
|
3937
|
+
for p2 in points[1:]:
|
3938
|
+
logger.debug("try from %s to %s", p1, p2)
|
3939
|
+
if not points_are_close(p1, p2):
|
3940
|
+
logger.debug("Line from %s to %s", p1, p2)
|
3941
|
+
if self._line_inside_not_iron(p1, p2):
|
3942
|
+
logger.debug("- not in iron (%s, %s)", p1, p2)
|
3943
|
+
p1 = p2
|
3944
|
+
continue
|
3945
|
+
|
3946
|
+
line = Line(Element(start=p1, end=p2),
|
3947
|
+
color='darkred',
|
3948
|
+
linestyle='dotted')
|
3949
|
+
line.set_attribute('iron_sep')
|
3950
|
+
self.add_element(line,
|
3951
|
+
rtol=self.rtol,
|
3952
|
+
atol=self.atol)
|
3953
|
+
logger.debug("add line(%s)", line)
|
3954
|
+
created = True
|
3955
|
+
p1 = p2
|
3956
|
+
logger.debug("end of create_lines_outside_magnets")
|
3957
|
+
return created
|
3958
|
+
|
3789
3959
|
def has_areas_touching_both_sides(self):
|
3790
3960
|
for a in self.area_list:
|
3791
3961
|
if a.is_touching_both_sides():
|
@@ -3842,9 +4012,146 @@ class Geometry(object):
|
|
3842
4012
|
logger.debug("end of get_inner_airgap_line #%s", len(nodes))
|
3843
4013
|
return nodes, elements
|
3844
4014
|
|
3845
|
-
def
|
4015
|
+
def create_inner_corner_areas(self, startangle, endangle):
|
3846
4016
|
self.set_edge_attributes()
|
3847
|
-
|
4017
|
+
|
4018
|
+
builder = AreaBuilder(geom=self)
|
4019
|
+
builder.create_inner_corner_auxiliary_areas(startangle, endangle)
|
4020
|
+
|
4021
|
+
def repair_border_line(self, nodes):
|
4022
|
+
logger.debug("begin repair_border_line")
|
4023
|
+
for d, n, ok in nodes:
|
4024
|
+
logger.debug(" node=%s, ok=%s", n, ok)
|
4025
|
+
|
4026
|
+
d1, n1, ok1 = nodes[0]
|
4027
|
+
if not ok1: # fatal => ignore
|
4028
|
+
logger.debug("end repair_border_line: missing point %s", n1)
|
4029
|
+
return False
|
4030
|
+
d1, n1, ok1 = nodes[-1]
|
4031
|
+
if not ok1: # fatal => ignore
|
4032
|
+
logger.debug("end repair_border_line: missing point %s", n1)
|
4033
|
+
return False
|
4034
|
+
|
4035
|
+
remove_n1 = None
|
4036
|
+
for d2, n2, ok2 in nodes[1:]:
|
4037
|
+
if ok1 and not ok2:
|
4038
|
+
remove_n1 = n1
|
4039
|
+
if ok2 and remove_n1:
|
4040
|
+
try:
|
4041
|
+
self._remove_edge(remove_n1, n2)
|
4042
|
+
logger.debug("Remove Line %s -- %s", remove_n1, n2)
|
4043
|
+
except nx.NetworkXError:
|
4044
|
+
logger.debug("Warning: Remove Line %s -- %s failed", remove_n1, n2)
|
4045
|
+
logger.debug("end repair_border_line: failed")
|
4046
|
+
return False
|
4047
|
+
remove_n1 = None
|
4048
|
+
n1 = n2
|
4049
|
+
ok1 = ok2
|
4050
|
+
|
4051
|
+
d1, n1, ok1 = nodes[0]
|
4052
|
+
for d2, n2, ok2 in nodes[1:]:
|
4053
|
+
if not ok2: # new node
|
4054
|
+
self.add_line(n1, n2)
|
4055
|
+
logger.debug("Add Line %s -- %s", n1, n2)
|
4056
|
+
elif not ok1:
|
4057
|
+
self.add_line(n1, n2)
|
4058
|
+
logger.debug("Add Line %s -- %s", n1, n2)
|
4059
|
+
n1 = n2
|
4060
|
+
ok1 = ok2
|
4061
|
+
logger.debug("end repair_border_line")
|
4062
|
+
return True
|
4063
|
+
|
4064
|
+
def create_boundery_nodes(self,
|
4065
|
+
center,
|
4066
|
+
startangle,
|
4067
|
+
endangle,
|
4068
|
+
rtol=None, atol=None):
|
4069
|
+
if not rtol:
|
4070
|
+
rtol = 1e-4
|
4071
|
+
if not atol:
|
4072
|
+
atol = 1e-3
|
4073
|
+
|
4074
|
+
start_nodes = [n for n in self.angle_nodes(center, startangle, rtol, atol)]
|
4075
|
+
end_nodes = [n for n in self.angle_nodes(center, endangle, rtol, atol)]
|
4076
|
+
alpha = alpha_angle(startangle, endangle)
|
4077
|
+
|
4078
|
+
logger.debug("begin of create_boundery_nodes")
|
4079
|
+
start_rot_nodes = self.rotate_nodes(alpha, start_nodes)
|
4080
|
+
end_rot_nodes = self.rotate_nodes(-alpha, end_nodes)
|
4081
|
+
|
4082
|
+
def miss_nodelist(src_nodelist, dest_nodelist):
|
4083
|
+
nlist = []
|
4084
|
+
for src_n in src_nodelist:
|
4085
|
+
ok = False
|
4086
|
+
for dest_n in dest_nodelist:
|
4087
|
+
if points_are_close(src_n, dest_n, rtol=rtol, atol=atol):
|
4088
|
+
ok = True
|
4089
|
+
break
|
4090
|
+
if not ok:
|
4091
|
+
nlist.append(src_n)
|
4092
|
+
return nlist
|
4093
|
+
|
4094
|
+
logger.debug("Begin with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
|
4095
|
+
|
4096
|
+
missing_end_nodes = miss_nodelist(start_rot_nodes, end_nodes)
|
4097
|
+
missing_start_nodes = miss_nodelist(end_rot_nodes, start_nodes)
|
4098
|
+
|
4099
|
+
if missing_start_nodes:
|
4100
|
+
logger.debug("%s missing start nodes", len(missing_start_nodes))
|
4101
|
+
start_nodes = [(distance(center, n), n, True) for n in start_nodes]
|
4102
|
+
for n in missing_start_nodes:
|
4103
|
+
start_nodes.append((distance(center, n), n, False))
|
4104
|
+
start_nodes.sort()
|
4105
|
+
if not self.repair_border_line(start_nodes):
|
4106
|
+
logger.debug("end of create_boundery_nodes (failed)")
|
4107
|
+
return
|
4108
|
+
else:
|
4109
|
+
start_nodes = [(distance(center, n), n, True) for n in start_nodes]
|
4110
|
+
start_nodes.sort()
|
4111
|
+
|
4112
|
+
if missing_end_nodes:
|
4113
|
+
logger.debug("%s missing end nodes", len(missing_end_nodes))
|
4114
|
+
end_nodes = [(distance(center, n), n, True) for n in end_nodes]
|
4115
|
+
for n in missing_end_nodes:
|
4116
|
+
end_nodes.append((distance(center, n), n, False))
|
4117
|
+
end_nodes.sort()
|
4118
|
+
if not self.repair_border_line(end_nodes):
|
4119
|
+
logger.debug("end of create_boundery_nodes (failed)")
|
4120
|
+
return
|
4121
|
+
else:
|
4122
|
+
end_nodes = [(distance(center, n), n, True) for n in end_nodes]
|
4123
|
+
end_nodes.sort()
|
4124
|
+
|
4125
|
+
start_nodes = [(distance(center, n), n)
|
4126
|
+
for n in self.angle_nodes(center, startangle, rtol, atol)]
|
4127
|
+
start_nodes.sort()
|
4128
|
+
end_nodes = [(distance(center, n), n)
|
4129
|
+
for n in self.angle_nodes(center, endangle, rtol, atol)]
|
4130
|
+
end_nodes.sort()
|
4131
|
+
|
4132
|
+
logger.debug("End with Nodes Start=%s, End=%s", len(start_nodes), len(end_nodes))
|
4133
|
+
|
4134
|
+
nodes = [n for d, n in start_nodes]
|
4135
|
+
start_rot_nodes = self.rotate_nodes(alpha, nodes)
|
4136
|
+
|
4137
|
+
for d, node in start_nodes:
|
4138
|
+
self.set_point_of_node(node, node)
|
4139
|
+
i = 0
|
4140
|
+
if len(end_nodes) == len(start_rot_nodes):
|
4141
|
+
for d, node in end_nodes:
|
4142
|
+
self.set_point_of_node(node, start_rot_nodes[i])
|
4143
|
+
i += 1
|
4144
|
+
|
4145
|
+
logger.debug("end of create_boundery_nodes")
|
4146
|
+
return
|
4147
|
+
|
4148
|
+
def set_point_of_node(self, node, p):
|
4149
|
+
if isinstance(node, list):
|
4150
|
+
node = (node[0], node[1])
|
4151
|
+
nbrs = self.get_neighbors(node)
|
4152
|
+
for nbr in nbrs:
|
4153
|
+
e = self.get_edge_element(node, nbr)
|
4154
|
+
e.replace_point(node, p)
|
3848
4155
|
|
3849
4156
|
def create_and_append_area(self, n1, n2):
|
3850
4157
|
rslt = self.get_new_area(n1, n2, False)
|
@@ -3852,7 +4159,7 @@ class Geometry(object):
|
|
3852
4159
|
if rslt.get('ok', False):
|
3853
4160
|
area = rslt['area']
|
3854
4161
|
a = Area(area, self.center, 0.0)
|
3855
|
-
a.
|
4162
|
+
a.set_type(AREA.TYPE_AIR) # air
|
3856
4163
|
self.area_list.append(a)
|
3857
4164
|
return True
|
3858
4165
|
logger.error("No area for air near airgap!!")
|
@@ -3904,7 +4211,9 @@ class Geometry(object):
|
|
3904
4211
|
self.add_line(start_cp, n,
|
3905
4212
|
color='red',
|
3906
4213
|
linestyle='dotted')
|
3907
|
-
self.
|
4214
|
+
self.add_element(start_line,
|
4215
|
+
rtol=self.rtol,
|
4216
|
+
atol=self.atol)
|
3908
4217
|
self.create_and_append_area(start_cp, n)
|
3909
4218
|
self.start_corners = self.get_corner_nodes(self.center,
|
3910
4219
|
0.0)
|
@@ -3931,7 +4240,9 @@ class Geometry(object):
|
|
3931
4240
|
self.add_line(end_cp, n,
|
3932
4241
|
color='red',
|
3933
4242
|
linestyle='dotted')
|
3934
|
-
self.
|
4243
|
+
self.add_element(end_line,
|
4244
|
+
rtol=self.rtol,
|
4245
|
+
atol=self.atol)
|
3935
4246
|
self.create_and_append_area(n, end_cp)
|
3936
4247
|
self.end_corners = self.get_corner_nodes(self.center,
|
3937
4248
|
self.alfa)
|