wolfhece 2.2.35__py3-none-any.whl → 2.2.37__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.
@@ -28,6 +28,7 @@ from matplotlib.figure import Figure
28
28
  from matplotlib import cm
29
29
  from matplotlib.colors import Colormap
30
30
  from matplotlib.tri import Triangulation as mpl_tri
31
+ import warnings
31
32
 
32
33
  import struct
33
34
  import pyvista as pv
@@ -66,13 +67,17 @@ class Triangulation(Element_To_Draw):
66
67
  super().__init__(idx, plotted, mapviewer, need_for_wx)
67
68
 
68
69
  self.filename = ''
70
+
69
71
  self.tri= tri
70
72
  self.pts = pts
73
+
71
74
  self.id_list = -99999
72
75
 
73
76
  self.nb_tri = len(tri)
74
77
  self.nb_pts = len(pts)
75
78
 
79
+ self._used_tri = [True] * self.nb_tri
80
+
76
81
  self._move_start = None
77
82
  self._move_step = None # step for a move
78
83
  self._rotation_center = None
@@ -408,10 +413,17 @@ class Triangulation(Element_To_Draw):
408
413
  else:
409
414
  glCallList(self.id_list)
410
415
 
411
- def plot_matplotlib(self, ax:Axes, color='black', alpha=1., lw=1.5, **kwargs):
416
+ def plot_matplotlib(self, ax:Axes | tuple[Figure, Axes] = None, color='black', alpha=1., lw=1.5, **kwargs):
412
417
  """ Plot the triangulation in Matplotlib
413
418
  """
414
419
 
420
+ if isinstance(ax, tuple):
421
+ fig, ax = ax
422
+ elif ax is None:
423
+ fig, ax = plt.subplots()
424
+ else:
425
+ fig = ax.figure
426
+
415
427
  if self.nb_tri>0:
416
428
  for curtri in self.tri:
417
429
  x = [self.pts[curtri[0]][0], self.pts[curtri[1]][0], self.pts[curtri[2]][0], self.pts[curtri[0]][0]]
@@ -420,6 +432,8 @@ class Triangulation(Element_To_Draw):
420
432
  else:
421
433
  logging.warning('No triangles to plot')
422
434
 
435
+ return fig, ax
436
+
423
437
  @property
424
438
  def mpl_triangulation(self) -> mpl_tri:
425
439
  """ Return the triangulation as a Matplotlib Triangulation object """
@@ -429,13 +443,24 @@ class Triangulation(Element_To_Draw):
429
443
  logging.warning('No triangles to plot')
430
444
  return None
431
445
 
432
- def plot_matplotlib_3D(self, ax:Axes, color='black', alpha=0.2, lw=1.5, edgecolor='k', shade=True, **kwargs):
446
+ def plot_matplotlib_3D(self, ax:Axes | tuple[Figure, Axes] = None, color='black', alpha=0.2, lw=1.5, edgecolor='k', shade=True, **kwargs):
433
447
  """ Plot the triangulation in Matplotlib 3D
434
448
  """
449
+
435
450
  if self.nb_tri>0:
451
+ if isinstance(ax, tuple):
452
+ fig, ax = ax
453
+ elif ax is None:
454
+ fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
455
+ else:
456
+ fig = ax.figure
457
+
436
458
  ax.plot_trisurf(self.mpl_triangulation, Z=self.pts[:,2], color=color, alpha=alpha, lw=lw, edgecolor=edgecolor, shade=shade, **kwargs)
459
+
460
+ return fig, ax
437
461
  else:
438
462
  logging.warning('No triangles to plot')
463
+ return None, None
439
464
 
440
465
  def find_minmax(self,force):
441
466
  """ Find the min and max of the triangulation
@@ -550,6 +575,45 @@ class Triangulation(Element_To_Draw):
550
575
  angle = np.round(angle/self._rotation_step)*self._rotation_step
551
576
 
552
577
  return self.rotate(-angle, center=self._rotation_center, use_cache=use_cache)
578
+
579
+ def _get_polygons(self) -> list[Polygon]:
580
+ """ Get the polygons from the triangulation """
581
+ polygons = []
582
+ for curtri in self.tri:
583
+ if len(curtri) == 3:
584
+ poly = Polygon([self.pts[curtri[0]][:2], self.pts[curtri[1]][:2], self.pts[curtri[2]][:2]])
585
+ if poly.is_valid:
586
+ polygons.append(poly)
587
+ else:
588
+ logging.warning('Invalid polygon found in triangulation: {}'.format(poly))
589
+ else:
590
+ logging.warning('Triangle with {} vertices found in triangulation: {}'.format(len(curtri), curtri))
591
+ return polygons
592
+
593
+ def unuse_triangles_containing_points(self, points:list[Point]):
594
+ """ Unuse triangles containing points """
595
+
596
+ polys = self._get_polygons()
597
+ for point in points:
598
+ for i, poly in enumerate(polys):
599
+ if poly.contains(point):
600
+ self._used_tri[i] = False
601
+
602
+ def get_triangles_as_listwolfvertices(self, used_only:bool=True) -> list[list[wolfvertex]]:
603
+ """ Get the triangles as a list of wolfvertex objects """
604
+
605
+ triangles = []
606
+ for i, curtri in enumerate(self.tri):
607
+ if not used_only or (used_only and self._used_tri[i]):
608
+ if len(curtri) == 3:
609
+ v1 = wolfvertex(self.pts[curtri[0]][0], self.pts[curtri[0]][1], self.pts[curtri[0]][2])
610
+ v2 = wolfvertex(self.pts[curtri[1]][0], self.pts[curtri[1]][1], self.pts[curtri[1]][2])
611
+ v3 = wolfvertex(self.pts[curtri[2]][0], self.pts[curtri[2]][1], self.pts[curtri[2]][2])
612
+ triangles.append([v1, v2, v3])
613
+ else:
614
+ logging.warning('Triangle with {} vertices found in triangulation: {}'.format(len(curtri), curtri))
615
+ return triangles
616
+
553
617
  class vectorproperties:
554
618
  """ Vector properties """
555
619
  used:bool
@@ -2212,6 +2276,81 @@ class vector:
2212
2276
 
2213
2277
  return len(not_in_use) > 0
2214
2278
 
2279
+ def check_if_interior_exists(self):
2280
+ """ Check if the vector has an interior and adapt in_use accordingly.
2281
+
2282
+ The verification is only made in 2D, as the interior is defined as a pair of segments that correspond exactly to the same coordinates.
2283
+ Z coordinates are not taken into account in this verification.
2284
+
2285
+ """
2286
+
2287
+ xy = self.xy
2288
+ if self.closed and (xy[0,0] == xy[-1,0] and xy[0,1] == xy[-1,1]):
2289
+ # If the vector is closed, we remove the last vertex to avoid checking it
2290
+ xy = xy[:-1]
2291
+
2292
+ xy_unique, inverse, count = np.unique(xy, return_inverse=True, return_counts=True, axis=0)
2293
+
2294
+ duplicate_found = False
2295
+
2296
+ if xy.shape[0] != xy_unique.shape[0]:
2297
+ # There are duplicates, we need to test if the duplicate form a segment
2298
+
2299
+ # Find the duplicate indices
2300
+ duplicate_indices = np.where(count > 1)[0]
2301
+ # Find the inverse indices of the duplicates
2302
+ duplicate_indices = np.where(np.isin(inverse, duplicate_indices))[0]
2303
+ diff = np.diff(duplicate_indices)
2304
+
2305
+ for i in range(len(diff)):
2306
+ # Set the in_use property to False for the vertices that are not used
2307
+ if diff[i] == 1:
2308
+ self.myvertices[duplicate_indices[i+1]].in_use = False
2309
+ duplicate_found = True
2310
+
2311
+ if duplicate_found:
2312
+ self.reset_linestring()
2313
+ self._reset_listogl()
2314
+
2315
+
2316
+ @property
2317
+ def nb_interiors(self) -> int:
2318
+ """ Return the number of interiors in the vector.
2319
+
2320
+ If the vector is filled, it returns the number of pairs of vertices not in use.
2321
+ If the vector is not filled, it returns the number of vertices not in use.
2322
+ """
2323
+ not_in_use = [curvert for curvert in self.myvertices if not curvert.in_use]
2324
+
2325
+ return len(not_in_use) // 2 if self.myprop.filled else len(not_in_use)
2326
+
2327
+ @property
2328
+ def _parts(self) -> "zone":
2329
+ """ Return the parts of the vector as a zone.
2330
+
2331
+ Useful for creating subpolygons or triangulation.
2332
+ """
2333
+ self.find_minmax()
2334
+
2335
+ parts = zone()
2336
+ current_part = vector()
2337
+ for curvert in self.myvertices:
2338
+ if curvert.in_use:
2339
+ current_part.add_vertex(curvert)
2340
+ else:
2341
+ if current_part.nbvertices > 0:
2342
+ if parts.nbvectors > 0:
2343
+ current_part.force_to_close()
2344
+ parts.add_vector(current_part)
2345
+ current_part = vector()
2346
+
2347
+ for curvert in current_part.myvertices:
2348
+ parts.myvectors[0].add_vertex(curvert)
2349
+
2350
+ parts.myvectors[0].force_to_close()
2351
+
2352
+ return parts
2353
+
2215
2354
  def get_subpolygons(self) -> list[list[wolfvertex]]:
2216
2355
  """
2217
2356
  Return a list of polygons from the vector
@@ -2223,10 +2362,41 @@ class vector:
2223
2362
  return []
2224
2363
 
2225
2364
  if self.myprop.filled:
2226
- if self.myprop.closed and (self.myvertices[0].x != self.myvertices[-1].x or self.myvertices[0].y != self.myvertices[-1].y):
2227
- return [self.myvertices + [self.myvertices[0]]]
2365
+ if self.has_interior:
2366
+ #En attendant de lier WOLF-Fortran, on utilise la triangulation contrainte de la librairie Triangle -- https://rufat.be/triangle/
2367
+
2368
+ parts = self._parts
2369
+ tri = parts.create_constrainedDelaunay(nb = 0)
2370
+ centroid_interiors = [part.centroid for part in parts.myvectors[1:]]
2371
+ tri.unuse_triangles_containing_points(centroid_interiors)
2372
+
2373
+ return tri.get_triangles_as_listwolfvertices()
2374
+
2228
2375
  else:
2229
- return [self.myvertices]
2376
+ # if self.myprop.closed and (self.myvertices[0].x != self.myvertices[-1].x or self.myvertices[0].y != self.myvertices[-1].y):
2377
+ # return [self.myvertices + [self.myvertices[0]]]
2378
+ # else:
2379
+ # return [self.myvertices]
2380
+ xx, yy = self.polygon.exterior.xy
2381
+
2382
+ # On translate les coordonnées pour éviter les erreurs de triangulation
2383
+ tr_x = np.array(xx).min()
2384
+ tr_y = np.array(yy).min()
2385
+
2386
+ xx = np.array(xx)-tr_x
2387
+ yy = np.array(yy)-tr_y
2388
+
2389
+ geom = {'vertices' : [[x,y] for x,y in zip(xx[:-1],yy[:-1])], 'segments' : [[i,i+1] for i in range(len(xx)-2)]+[[len(xx)-2,0]]}
2390
+
2391
+ try:
2392
+ delaunay = triangle.triangulate(geom, 'p')
2393
+ tri = []
2394
+ for curtri in delaunay['triangles']:
2395
+ # on traduit les coordonnées pour revenir dans le monde réel
2396
+ tri.append([wolfvertex(delaunay['vertices'][curtri[i]][0] + tr_x, delaunay['vertices'][curtri[i]][1] + tr_y) for i in range(3)])
2397
+ return tri
2398
+ except:
2399
+ pass
2230
2400
 
2231
2401
  else:
2232
2402
  if self.has_interior:
@@ -2396,28 +2566,35 @@ class vector:
2396
2566
  logging.debug(_('Polygon not in Polygon'))
2397
2567
 
2398
2568
  else:
2399
- #En attendant de lier WOLF-Fortran, on utilise la triangulation contrainte de la librairie Triangle -- https://rufat.be/triangle/
2400
- xx, yy = ls.exterior.xy
2401
-
2402
- # On translate les coordonnées pour éviter les erreurs de triangulation
2403
- tr_x = np.array(xx).min()
2404
- tr_y = np.array(yy).min()
2405
-
2406
- xx = np.array(xx)-tr_x
2407
- yy = np.array(yy)-tr_y
2408
-
2409
- geom = {'vertices' : [[x,y] for x,y in zip(xx[:-1],yy[:-1])], 'segments' : [[i,i+1] for i in range(len(xx)-2)]+[[len(xx)-2,0]]}
2410
-
2411
- try:
2412
- delaunay = triangle.triangulate(geom, 'p')
2413
- for curtri in delaunay['triangles']:
2414
- glBegin(GL_POLYGON)
2415
- for i in range(3):
2416
- # on retraduit les coordonnées pour revenir dans le monde réel
2417
- glVertex2d(delaunay['vertices'][curtri[i]][0] + tr_x, delaunay['vertices'][curtri[i]][1] + tr_y)
2418
- glEnd()
2419
- except:
2420
- pass
2569
+ # #En attendant de lier WOLF-Fortran, on utilise la triangulation contrainte de la librairie Triangle -- https://rufat.be/triangle/
2570
+ # xx, yy = ls.exterior.xy
2571
+
2572
+ # # On translate les coordonnées pour éviter les erreurs de triangulation
2573
+ # tr_x = np.array(xx).min()
2574
+ # tr_y = np.array(yy).min()
2575
+
2576
+ # xx = np.array(xx)-tr_x
2577
+ # yy = np.array(yy)-tr_y
2578
+
2579
+ # geom = {'vertices' : [[x,y] for x,y in zip(xx[:-1],yy[:-1])], 'segments' : [[i,i+1] for i in range(len(xx)-2)]+[[len(xx)-2,0]]}
2580
+
2581
+ # try:
2582
+ # delaunay = triangle.triangulate(geom, 'p')
2583
+ # for curtri in delaunay['triangles']:
2584
+ # glBegin(GL_POLYGON)
2585
+ # for i in range(3):
2586
+ # # on retraduit les coordonnées pour revenir dans le monde réel
2587
+ # glVertex2d(delaunay['vertices'][curtri[i]][0] + tr_x, delaunay['vertices'][curtri[i]][1] + tr_y)
2588
+ # glEnd()
2589
+ # except:
2590
+ # pass
2591
+
2592
+ all_polys = self.get_subpolygons()
2593
+ for curpoly in all_polys:
2594
+ glBegin(GL_POLYGON)
2595
+ for curvertex in curpoly:
2596
+ glVertex2d(curvertex.x, curvertex.y)
2597
+ glEnd()
2421
2598
 
2422
2599
  else:
2423
2600
  all_polys = self.get_subpolygons()
@@ -2488,19 +2665,32 @@ class vector:
2488
2665
  else:
2489
2666
  logging.warning(_('No image texture available for plot'))
2490
2667
 
2491
- def plot_matplotlib(self, ax:plt.Axes):
2668
+ def plot_matplotlib(self, ax:plt.Axes | tuple[Figure, Axes] = None):
2492
2669
  """
2493
- Plot Matplotlib
2670
+ Plot Matplotlib - XY coordinates ONLY
2671
+
2672
+ :param ax: Matplotlib Axes to plot on or a tuple (fig, ax) where fig is the figure and ax is the axes.
2673
+ If ax is None, a new figure and axes will be created.
2494
2674
  """
2495
2675
 
2676
+ if isinstance(ax, tuple):
2677
+ # if ax is a tuple, we assume it is (fig, ax)
2678
+ fig, ax = ax
2679
+ elif ax is None:
2680
+ fig, ax = plt.subplots()
2681
+ else:
2682
+ fig = ax.figure
2683
+
2496
2684
  if self.myprop.used:
2497
2685
 
2498
2686
  if self.myprop.filled:
2499
2687
  rgb=getRGBfromI(self.myprop.color)
2500
- if self.myprop.transparent:
2501
- ax.fill([curvert.x for curvert in self.myvertices], [curvert.y for curvert in self.myvertices], color=(rgb[0]/255.,rgb[1]/255.,rgb[2]/255.,self.myprop.alpha))
2502
- else:
2503
- ax.fill([curvert.x for curvert in self.myvertices], [curvert.y for curvert in self.myvertices], color=(rgb[0]/255.,rgb[1]/255.,rgb[2]/255.))
2688
+ subpoly = self.get_subpolygons()
2689
+ for curpoly in subpoly:
2690
+ if self.myprop.transparent:
2691
+ ax.fill([curvert.x for curvert in curpoly], [curvert.y for curvert in curpoly], color=(rgb[0]/255.,rgb[1]/255.,rgb[2]/255.,self.myprop.alpha))
2692
+ else:
2693
+ ax.fill([curvert.x for curvert in curpoly], [curvert.y for curvert in curpoly], color=(rgb[0]/255.,rgb[1]/255.,rgb[2]/255.))
2504
2694
  else:
2505
2695
  rgb=getRGBfromI(self.myprop.color)
2506
2696
  subpoly = self.get_subpolygons()
@@ -2512,164 +2702,438 @@ class vector:
2512
2702
 
2513
2703
  self.plot_legend_mpl(ax)
2514
2704
 
2515
- def _get_textfont(self):
2516
- """ Retunr a 'Text_Infos' instance for the legend """
2517
-
2518
- r,g,b = getRGBfromI(self.myprop.legendcolor)
2519
- tinfos = Text_Infos(self.myprop.legendpriority,
2520
- (np.cos(self.myprop.legendorientation/180*np.pi),
2521
- np.sin(self.myprop.legendorientation/180*np.pi)),
2522
- self.myprop.legendfontname,
2523
- self.myprop.legendfontsize,
2524
- colour=(r,g,b,255),
2525
- dimsreal=(self.myprop.legendlength,
2526
- self.myprop.legendheight),
2527
- relative_position=self.myprop.legendrelpos)
2705
+ return fig, ax
2528
2706
 
2529
- return tinfos
2707
+ def plot_matplotlib_sz(self, ax:plt.Axes | tuple[Figure, Axes] = None):
2708
+ """
2709
+ Plot Matplotlib - SZ coordinates ONLY.
2530
2710
 
2531
- def _get_textfont_idx(self):
2532
- """ Retunr a 'Text_Infos' instance for the legend """
2711
+ S is the curvilinear abscissa, Z is the elevation.
2533
2712
 
2534
- r,g,b = getRGBfromI(self.myprop.color)
2535
- tinfos = Text_Infos(3,
2536
- (1., 0.),
2537
- self.myprop.legendfontname,
2538
- 12,
2539
- colour=(r,g,b,255),
2540
- dimsreal=(self.myprop.legendlength,
2541
- self.myprop.legendheight),
2542
- relative_position=7)
2713
+ :param ax: Matplotlib Axes to plot on or a tuple (fig, ax) where fig is the figure and ax is the axes.
2714
+ If ax is None, a new figure and axes will be created.
2715
+ """
2543
2716
 
2544
- return tinfos
2717
+ if isinstance(ax, tuple):
2718
+ # if ax is a tuple, we assume it is (fig, ax)
2719
+ fig, ax = ax
2720
+ elif ax is None:
2721
+ fig, ax = plt.subplots()
2722
+ else:
2723
+ fig = ax.figure
2545
2724
 
2546
- def add2tree(self, tree:TreeListCtrl, root):
2547
- """
2548
- Ajout de l'objte à un TreeListCtrl wx
2549
- """
2550
- self.mytree=tree
2551
- self.myitem=tree.AppendItem(root, self.myname,data=self)
2552
2725
  if self.myprop.used:
2553
- tree.CheckItem(self.myitem)
2726
+ s,z = self.sz_curvi
2554
2727
 
2555
- def unuse(self):
2556
- """
2557
- L'objet n'est plus à utiliser
2558
- """
2559
- self.myprop.used=False
2560
- if self.mytree is not None:
2561
- self.mytree.UncheckItem(self.myitem)
2728
+ rgb=getRGBfromI(self.myprop.color)
2729
+ if self.myprop.transparent:
2730
+ ax.plot(s, z, color=(rgb[0]/255., rgb[1]/255., rgb[2]/255., self.myprop.alpha), linewidth=self.myprop.width)
2731
+ else:
2732
+ ax.plot(s, z, color=(rgb[0]/255., rgb[1]/255., rgb[2]/255.), linewidth=self.myprop.width)
2562
2733
 
2563
- self._reset_listogl()
2734
+ return fig, ax
2564
2735
 
2565
- def use(self):
2736
+ def plot_linked(self, fig, ax, linked_arrays:dict):
2566
2737
  """
2567
- L'objet n'est plus à utiliser
2738
+ Graphique Matplolib de valeurs dans les matrices liées
2568
2739
  """
2569
- self.myprop.used=True
2570
- if self.mytree is not None:
2571
- self.mytree.CheckItem(self.myitem)
2572
-
2740
+ # from .wolf_array import WolfArray
2741
+ # from .wolfresults_2D import Wolfresults_2D
2573
2742
 
2574
- self._reset_listogl()
2743
+ colors=['red','blue','green']
2575
2744
 
2576
- def fillgrid(self, gridto:CpGrid):
2577
- """
2578
- Remplissage d'un CpGrid
2579
- """
2580
- curv:wolfvertex
2745
+ exit=True
2746
+ for curlabel, curarray in linked_arrays.items():
2747
+ if curarray.plotted:
2748
+ exit=False
2581
2749
 
2582
- gridto.SetColLabelValue(0,'X')
2583
- gridto.SetColLabelValue(1,'Y')
2584
- gridto.SetColLabelValue(2,'Z')
2585
- gridto.SetColLabelValue(3,'value')
2586
- gridto.SetColLabelValue(4,'s curvi')
2587
- gridto.SetColLabelValue(5,'in use')
2750
+ if exit:
2751
+ logging.warning(_('No plotted linked arrays'))
2752
+ return
2588
2753
 
2589
- nb=gridto.GetNumberRows()
2590
- if len(self.myvertices)-nb>0:
2591
- gridto.AppendRows(len(self.myvertices)-nb)
2592
2754
  k=0
2593
- for curv in self.myvertices:
2594
- gridto.SetCellValue(k,0,str(curv.x))
2595
- gridto.SetCellValue(k,1,str(curv.y))
2596
- gridto.SetCellValue(k,2,str(curv.z))
2597
- gridto.SetCellValue(k,5,'1' if curv.in_use else '0')
2598
- k+=1
2599
2755
 
2600
- def updatefromgrid(self,gridfrom:CpGrid):
2601
- """
2602
- Mise à jour depuis un CpGrid
2603
- """
2604
- curv:wolfvertex
2756
+ myls = self.asshapely_ls()
2757
+ length = myls.length
2758
+ tol=length/10.
2759
+ ax.set_xlim(0-tol,length+tol)
2605
2760
 
2606
- nbl=gridfrom.GetNumberRows()
2607
- k=0
2608
- while k<nbl:
2609
- x=gridfrom.GetCellValue(k,0)
2610
- y=gridfrom.GetCellValue(k,1)
2611
- z=gridfrom.GetCellValue(k,2)
2612
- inuse = gridfrom.GetCellValue(k,5)
2613
- if z=='':
2614
- z=0.
2615
- if x!='':
2616
- if k<self.nbvertices:
2617
- self.myvertices[k].x=float(x)
2618
- self.myvertices[k].y=float(y)
2619
- self.myvertices[k].z=float(z)
2620
- self.myvertices[k].in_use = inuse=='1'
2621
- else:
2622
- newvert=wolfvertex(float(x),float(y),float(z))
2623
- self.add_vertex(newvert)
2624
- k+=1
2625
- else:
2626
- break
2761
+ zmin=99999.
2762
+ zmax=-99999.
2763
+ nullvalue = -99999
2627
2764
 
2628
- while k<self.nbvertices:
2629
- self.myvertices.pop(k)
2765
+ for curlabel, curarray in linked_arrays.items():
2766
+ if curarray.plotted:
2630
2767
 
2631
- if self._linestring is not None or self._polygon is not None:
2632
- self.prepare_shapely()
2768
+ ds = curarray.get_dxdy_min()
2633
2769
 
2634
- self._reset_listogl()
2770
+ nb = int(np.ceil(length/ds*2))
2635
2771
 
2636
- def get_s2d(self) -> np.ndarray:
2637
- """
2638
- calcul et retour des positions curvilignes 2D
2639
- """
2640
- s2d=np.zeros(self.nbvertices)
2641
- for k in range(1,self.nbvertices):
2642
- s2d[k]=s2d[k-1]+self.myvertices[k-1].dist2D(self.myvertices[k])
2772
+ alls = np.linspace(0,int(length),nb)
2643
2773
 
2644
- return s2d
2774
+ pts = [myls.interpolate(curs) for curs in alls]
2645
2775
 
2646
- def get_s3d(self) -> np.ndarray:
2647
- """
2648
- calcul et retour des positions curvilignes 3D
2649
- """
2650
- s3d=np.zeros(self.nbvertices)
2651
- for k in range(1,self.nbvertices):
2652
- s3d[k]=s3d[k-1]+self.myvertices[k-1].dist3D(self.myvertices[k])
2776
+ allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
2653
2777
 
2654
- return s3d
2778
+ zmaxloc=np.max(allz[allz!=nullvalue])
2779
+ zminloc=np.min(allz[allz!=nullvalue])
2655
2780
 
2656
- def get_sz(self, cumul=True):
2657
- """
2658
- Calcule et retourne la distance horizontale cumulée ou non
2659
- de chaque point vis-à-vis du premier point
2781
+ zmax=max(zmax,zmaxloc)
2782
+ zmin=min(zmin,zminloc)
2660
2783
 
2661
- Utile pour le tracé de sections en travers ou des vérifications de position
2784
+ if np.max(allz)>nullvalue:
2785
+ # select parts
2786
+ if nullvalue in allz:
2787
+ # find all parts separated by nullvalue
2788
+ nulls = np.argwhere(allz==nullvalue)
2789
+ nulls = np.insert(nulls,0,-1)
2790
+ nulls = np.append(nulls,len(allz))
2662
2791
 
2663
- :param cumul: si True, retourne la distance cumulée 2D. si False, retourne la distance 2D entre chaque point et le premier.
2664
- """
2665
- z = np.asarray([self.myvertices[i].z for i in range(self.nbvertices)])
2792
+ addlabel = True
2793
+ for i in range(len(nulls)-1):
2794
+ if nulls[i+1]-nulls[i]>1:
2795
+ ax.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
2796
+ color=colors[np.mod(k,3)],
2797
+ lw=2.0,
2798
+ label=curlabel if addlabel else None)
2799
+ addlabel = False
2666
2800
 
2667
- nb = len(z)
2668
- s = np.zeros(nb)
2801
+ else:
2802
+ ax.plot(alls,allz,
2803
+ color=colors[np.mod(k,3)],
2804
+ lw=2.0,
2805
+ label=curlabel)
2806
+ k+=1
2669
2807
 
2670
- if cumul:
2671
- x1 = self.myvertices[0].x
2672
- y1 = self.myvertices[0].y
2808
+ ax.set_ylim(zmin,zmax)
2809
+ ax.legend()
2810
+ ax.grid()
2811
+ fig.canvas.draw()
2812
+
2813
+ return fig,ax
2814
+
2815
+ def plot_linked_wx(self, fig:MplFig, linked_arrays:dict):
2816
+ """
2817
+ Graphique Matplolib de valeurs dans les matrices liées.
2818
+
2819
+ Version pour wxPython
2820
+ """
2821
+
2822
+ colors=['red','blue','green']
2823
+
2824
+ exit=True
2825
+ for curlabel, curarray in linked_arrays.items():
2826
+ if curarray.plotted:
2827
+ exit=False
2828
+
2829
+ if exit:
2830
+ return
2831
+
2832
+ k=0
2833
+
2834
+ myls = self.asshapely_ls()
2835
+ length = myls.length
2836
+ tol=length/10.
2837
+ fig.cur_ax.set_xlim(0-tol,length+tol)
2838
+
2839
+ zmin=99999.
2840
+ zmax=-99999.
2841
+ nullvalue = -99999
2842
+
2843
+ for curlabel, curarray in linked_arrays.items():
2844
+ if curarray.plotted:
2845
+
2846
+ ds = curarray.get_dxdy_min()
2847
+
2848
+ nb = int(np.ceil(length/ds*2))
2849
+
2850
+ alls = np.linspace(0,int(length),nb)
2851
+
2852
+ pts = [myls.interpolate(curs) for curs in alls]
2853
+
2854
+ allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
2855
+
2856
+ zmaxloc=np.max(allz[allz!=nullvalue])
2857
+ zminloc=np.min(allz[allz!=nullvalue])
2858
+
2859
+ zmax=max(zmax,zmaxloc)
2860
+ zmin=min(zmin,zminloc)
2861
+
2862
+ if np.max(allz)>nullvalue:
2863
+ # select parts
2864
+ if nullvalue in allz:
2865
+ # find all parts separated by nullvalue
2866
+ nulls = np.argwhere(allz==nullvalue)
2867
+ nulls = np.insert(nulls,0,-1)
2868
+ nulls = np.append(nulls,len(allz))
2869
+
2870
+ addlabel = True
2871
+ for i in range(len(nulls)-1):
2872
+ if nulls[i+1]-nulls[i]>1:
2873
+ fig.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
2874
+ color=colors[np.mod(k,3)],
2875
+ lw=2.0,
2876
+ label=curlabel if addlabel else None)
2877
+ addlabel = False
2878
+
2879
+ else:
2880
+ fig.plot(alls,allz,
2881
+ color=colors[np.mod(k,3)],
2882
+ lw=2.0,
2883
+ label=curlabel)
2884
+ k+=1
2885
+
2886
+ fig.cur_ax.set_ylim(zmin,zmax)
2887
+ fig.cur_ax.legend()
2888
+ fig.cur_ax.grid()
2889
+
2890
+ return fig
2891
+
2892
+ def plot_mpl(self, show=False,
2893
+ forceaspect=True,
2894
+ fig:Figure=None,
2895
+ ax:Axes=None,
2896
+ labels:dict={},
2897
+ clear_ax:bool =True):
2898
+ """
2899
+ Graphique Matplolib du vecteur - SZ coordinates ONLY
2900
+
2901
+ DEPRECATED: Use plot_matplotlib_sz instead.
2902
+ """
2903
+ warnings.warn("plot_mpl is deprecated, use plot_matplotlib_sz instead", DeprecationWarning, stacklevel=2)
2904
+
2905
+ x,y=self.get_sz()
2906
+
2907
+ xmin=x[0]
2908
+ xmax=x[-1]
2909
+ ymin=np.min(y)
2910
+ ymax=np.max(y)
2911
+
2912
+ if ax is None:
2913
+ redraw=False
2914
+ fig = plt.figure()
2915
+ ax=fig.add_subplot(111)
2916
+ else:
2917
+ redraw=True
2918
+ if clear_ax:
2919
+ # Clear the axes if specified
2920
+ ax.cla()
2921
+
2922
+ if 'title' in labels.keys():
2923
+ ax.set_title(labels['title'])
2924
+ if 'xlabel' in labels.keys():
2925
+ ax.set_xlabel(labels['xlabel'])
2926
+ if 'ylabel' in labels.keys():
2927
+ ax.set_ylabel(labels['ylabel'])
2928
+
2929
+ if ymax>-99999.:
2930
+
2931
+ dy=ymax-ymin
2932
+ ymin-=dy/4.
2933
+ ymax+=dy/4.
2934
+
2935
+ ax.plot(x,y,color='black',
2936
+ lw=2.0,
2937
+ label=self.myname)
2938
+
2939
+ ax.legend()
2940
+
2941
+ tol=(xmax-xmin)/10.
2942
+ ax.set_xlim(xmin-tol,xmax+tol)
2943
+ ax.set_ylim(ymin,ymax)
2944
+
2945
+ if forceaspect:
2946
+ aspect=1.0*(ymax-ymin)/(xmax-xmin)*(ax.get_xlim()[1] - ax.get_xlim()[0]) / (ax.get_ylim()[1] - ax.get_ylim()[0])
2947
+ ax.set_aspect(aspect)
2948
+
2949
+ if show:
2950
+ fig.show()
2951
+
2952
+ if redraw:
2953
+ fig.canvas.draw()
2954
+
2955
+ return fig,ax
2956
+
2957
+ def _get_textfont(self):
2958
+ """ Retunr a 'Text_Infos' instance for the legend """
2959
+
2960
+ r,g,b = getRGBfromI(self.myprop.legendcolor)
2961
+ tinfos = Text_Infos(self.myprop.legendpriority,
2962
+ (np.cos(self.myprop.legendorientation/180*np.pi),
2963
+ np.sin(self.myprop.legendorientation/180*np.pi)),
2964
+ self.myprop.legendfontname,
2965
+ self.myprop.legendfontsize,
2966
+ colour=(r,g,b,255),
2967
+ dimsreal=(self.myprop.legendlength,
2968
+ self.myprop.legendheight),
2969
+ relative_position=self.myprop.legendrelpos)
2970
+
2971
+ return tinfos
2972
+
2973
+ def _get_textfont_idx(self):
2974
+ """ Retunr a 'Text_Infos' instance for the legend """
2975
+
2976
+ r,g,b = getRGBfromI(self.myprop.color)
2977
+ tinfos = Text_Infos(3,
2978
+ (1., 0.),
2979
+ self.myprop.legendfontname,
2980
+ 12,
2981
+ colour=(r,g,b,255),
2982
+ dimsreal=(self.myprop.legendlength,
2983
+ self.myprop.legendheight),
2984
+ relative_position=7)
2985
+
2986
+ return tinfos
2987
+
2988
+ def add2tree(self, tree:TreeListCtrl, root):
2989
+ """
2990
+ Ajout de l'objte à un TreeListCtrl wx
2991
+ """
2992
+ self.mytree=tree
2993
+ self.myitem=tree.AppendItem(root, self.myname,data=self)
2994
+ if self.myprop.used:
2995
+ tree.CheckItem(self.myitem)
2996
+
2997
+ def unuse(self):
2998
+ """
2999
+ L'objet n'est plus à utiliser
3000
+ """
3001
+ self.myprop.used=False
3002
+ if self.mytree is not None:
3003
+ self.mytree.UncheckItem(self.myitem)
3004
+
3005
+ self._reset_listogl()
3006
+
3007
+ def use(self):
3008
+ """
3009
+ L'objet n'est plus à utiliser
3010
+ """
3011
+ self.myprop.used=True
3012
+ if self.mytree is not None:
3013
+ self.mytree.CheckItem(self.myitem)
3014
+
3015
+
3016
+ self._reset_listogl()
3017
+
3018
+ def fillgrid(self, gridto:CpGrid):
3019
+ """
3020
+ Remplissage d'un CpGrid
3021
+ """
3022
+ curv:wolfvertex
3023
+
3024
+ gridto.SetColLabelValue(0,'X')
3025
+ gridto.SetColLabelValue(1,'Y')
3026
+ gridto.SetColLabelValue(2,'Z')
3027
+ gridto.SetColLabelValue(3,'value')
3028
+ gridto.SetColLabelValue(4,'s curvi')
3029
+ gridto.SetColLabelValue(5,'in use')
3030
+
3031
+ nb=gridto.GetNumberRows()
3032
+ if len(self.myvertices)-nb>0:
3033
+ gridto.AppendRows(len(self.myvertices)-nb)
3034
+ k=0
3035
+ for curv in self.myvertices:
3036
+ gridto.SetCellValue(k,0,str(curv.x))
3037
+ gridto.SetCellValue(k,1,str(curv.y))
3038
+ gridto.SetCellValue(k,2,str(curv.z))
3039
+ gridto.SetCellValue(k,5,'1' if curv.in_use else '0')
3040
+ k+=1
3041
+
3042
+ def _fillgrid_only_i(self, gridto:CpGrid):
3043
+ """
3044
+ Remplissage d'un CpGrid
3045
+ """
3046
+ curv:wolfvertex
3047
+
3048
+ gridto.SetColLabelValue(0,'X')
3049
+ gridto.SetColLabelValue(1,'Y')
3050
+ gridto.SetColLabelValue(2,'Z')
3051
+ gridto.SetColLabelValue(3,'value')
3052
+ gridto.SetColLabelValue(4,'s curvi')
3053
+ gridto.SetColLabelValue(5,'in use')
3054
+
3055
+ nb=gridto.GetNumberRows()
3056
+ if len(self.myvertices)-nb>0:
3057
+ gridto.AppendRows(len(self.myvertices)-nb)
3058
+ k=0
3059
+
3060
+ for curv in self.myvertices:
3061
+ gridto.SetCellValue(k, 5, '1' if curv.in_use else '0')
3062
+ k+=1
3063
+
3064
+ def updatefromgrid(self,gridfrom:CpGrid):
3065
+ """
3066
+ Mise à jour depuis un CpGrid
3067
+ """
3068
+ curv:wolfvertex
3069
+
3070
+ nbl=gridfrom.GetNumberRows()
3071
+ k=0
3072
+ while k<nbl:
3073
+ x=gridfrom.GetCellValue(k,0)
3074
+ y=gridfrom.GetCellValue(k,1)
3075
+ z=gridfrom.GetCellValue(k,2)
3076
+ inuse = gridfrom.GetCellValue(k,5)
3077
+ if z=='':
3078
+ z=0.
3079
+ if x!='':
3080
+ if k<self.nbvertices:
3081
+ self.myvertices[k].x=float(x)
3082
+ self.myvertices[k].y=float(y)
3083
+ self.myvertices[k].z=float(z)
3084
+ self.myvertices[k].in_use = inuse=='1'
3085
+ else:
3086
+ newvert=wolfvertex(float(x),float(y),float(z))
3087
+ self.add_vertex(newvert)
3088
+ k+=1
3089
+ else:
3090
+ break
3091
+
3092
+ while k<self.nbvertices:
3093
+ self.myvertices.pop(k)
3094
+
3095
+ if self._linestring is not None or self._polygon is not None:
3096
+ self.prepare_shapely()
3097
+
3098
+ self._reset_listogl()
3099
+
3100
+ def get_s2d(self) -> np.ndarray:
3101
+ """
3102
+ calcul et retour des positions curvilignes 2D
3103
+ """
3104
+ s2d=np.zeros(self.nbvertices)
3105
+ for k in range(1,self.nbvertices):
3106
+ s2d[k]=s2d[k-1]+self.myvertices[k-1].dist2D(self.myvertices[k])
3107
+
3108
+ return s2d
3109
+
3110
+ def get_s3d(self) -> np.ndarray:
3111
+ """
3112
+ calcul et retour des positions curvilignes 3D
3113
+ """
3114
+ s3d=np.zeros(self.nbvertices)
3115
+ for k in range(1,self.nbvertices):
3116
+ s3d[k]=s3d[k-1]+self.myvertices[k-1].dist3D(self.myvertices[k])
3117
+
3118
+ return s3d
3119
+
3120
+ def get_sz(self, cumul=True):
3121
+ """
3122
+ Calcule et retourne la distance horizontale cumulée ou non
3123
+ de chaque point vis-à-vis du premier point
3124
+
3125
+ Utile pour le tracé de sections en travers ou des vérifications de position
3126
+
3127
+ :param cumul: si True, retourne la distance cumulée 2D. si False, retourne la distance 2D entre chaque point et le premier.
3128
+ """
3129
+ z = np.asarray([self.myvertices[i].z for i in range(self.nbvertices)])
3130
+
3131
+ nb = len(z)
3132
+ s = np.zeros(nb)
3133
+
3134
+ if cumul:
3135
+ x1 = self.myvertices[0].x
3136
+ y1 = self.myvertices[0].y
2673
3137
  for i in range(nb-1):
2674
3138
  x2 = self.myvertices[i+1].x
2675
3139
  y2 = self.myvertices[i+1].y
@@ -2878,346 +3342,135 @@ class vector:
2878
3342
  else:
2879
3343
  for k in range(k1+1,k2+1,-1):
2880
3344
  if self.myvertices[k].dist2D(newvec.myvertices[-1])!=0.:
2881
- newvec.add_vertex(self.myvertices[k])
2882
-
2883
- if [v2.x,v2.y,v2.z] != [newvec.myvertices[-1].x,newvec.myvertices[-1].y,newvec.myvertices[-1].z]:
2884
- newvec.add_vertex(v2)
2885
-
2886
- # if newvec.nbvertices==0:
2887
- # a=1
2888
- # if newvec.nbvertices==1:
2889
- # a=1
2890
- # newvec.update_lengths()
2891
- # if np.min(newvec._lengthparts2D)==0.:
2892
- # a=1
2893
- return newvec
2894
-
2895
- def get_values_linked_polygon(self, linked_arrays:list, getxy=False) -> dict:
2896
- """
2897
- Retourne les valeurs contenue dans le polygone
2898
-
2899
- linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
2900
- """
2901
- vals={}
2902
-
2903
- for curarray in linked_arrays:
2904
- if curarray.plotted:
2905
- vals[curarray.idx] = curarray.get_values_insidepoly(self, getxy=getxy)
2906
- else:
2907
- vals[curarray.idx] = None
2908
-
2909
- return vals
2910
-
2911
- def get_all_values_linked_polygon(self, linked_arrays, getxy=False) -> dict:
2912
- """
2913
- Retourne toutes les valeurs contenue dans le polygone --> utile au moins pour les résultats WOLF2D
2914
-
2915
- linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
2916
- """
2917
- vals={}
2918
-
2919
- for curarray in linked_arrays:
2920
- if curarray.plotted:
2921
- vals[curarray.idx] = curarray.get_all_values_insidepoly(self, getxy=getxy)
2922
- else:
2923
- vals[curarray.idx] = None
2924
-
2925
- return vals
2926
-
2927
- def get_all_values_linked_polyline(self,linked_arrays, getxy=True) -> dict:
2928
- """
2929
- Retourne toutes les valeurs sous la polyligne --> utile au moins pour les résultats WOLF2D
2930
-
2931
- linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
2932
- """
2933
- vals={}
2934
-
2935
- for curarray in linked_arrays:
2936
- if curarray.plotted:
2937
- vals[curarray.idx], xy = curarray.get_all_values_underpoly(self, getxy=getxy)
2938
- else:
2939
- vals[curarray.idx] = None
2940
-
2941
- return vals
2942
-
2943
- def get_values_on_vertices(self,curarray):
2944
- """
2945
- Récupération des valeurs sous les vertices et stockage dans la coordonnée 'z'
2946
- """
2947
- if not curarray.plotted:
2948
- return
2949
-
2950
- for curpt in self.myvertices:
2951
- curpt.z = curarray.get_value(curpt.x,curpt.y)
2952
-
2953
- def get_values_linked(self, linked_arrays:dict, refine=True, filter_null = False):
2954
- """
2955
- Récupération des valeurs dans les matrices liées sous les vertices et stockage dans la coordonnée 'z'
2956
- Possibilité de raffiner la discrétisation pour obtenir au moins une valeur par maille
2957
- """
2958
-
2959
- exit=True
2960
- for curlabel, curarray in linked_arrays.items():
2961
- if curarray.plotted:
2962
- # at least one plotted array
2963
- exit=False
2964
-
2965
- if exit:
2966
- return
2967
-
2968
- if refine:
2969
- myzone=zone(name='linked_arrays - fine step')
2970
-
2971
- for curlabel, curarray in linked_arrays.items():
2972
- if curarray.plotted:
2973
-
2974
- myvec=vector(name=curlabel,parentzone=myzone)
2975
- myzone.add_vector(myvec)
2976
-
2977
- ds = curarray.get_dxdy_min()
2978
-
2979
- pts = self._refine2D(ds)
2980
-
2981
- allz = [curarray.get_value(curpt.x, curpt.y, nullvalue=-99999) for curpt in pts]
2982
-
2983
- if filter_null:
2984
- for curpt,curz in zip(pts,allz):
2985
- if curz!=-99999:
2986
- myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
2987
- else:
2988
- for curpt,curz in zip(pts,allz):
2989
- myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
2990
-
2991
- else:
2992
- myzone=zone(name='linked_arrays')
2993
- for curlabel, curarray in linked_arrays.items():
2994
- if curarray.plotted:
2995
-
2996
- myvec=vector(name=curlabel,parentzone=myzone)
2997
- myzone.add_vector(myvec)
2998
-
2999
- if filter_null:
3000
- for curpt in self.myvertices:
3001
- locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3002
- if locval !=-99999:
3003
- myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3004
- else:
3005
- for curpt in self.myvertices:
3006
- locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3007
- myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3008
-
3009
- return myzone
3010
-
3011
- def plot_linked(self, fig, ax, linked_arrays:dict):
3012
- """
3013
- Graphique Matplolib de valeurs dans les matrices liées
3014
- """
3015
- # from .wolf_array import WolfArray
3016
- # from .wolfresults_2D import Wolfresults_2D
3017
-
3018
- colors=['red','blue','green']
3019
-
3020
- exit=True
3021
- for curlabel, curarray in linked_arrays.items():
3022
- if curarray.plotted:
3023
- exit=False
3024
-
3025
- if exit:
3026
- logging.warning(_('No plotted linked arrays'))
3027
- return
3028
-
3029
- k=0
3030
-
3031
- myls = self.asshapely_ls()
3032
- length = myls.length
3033
- tol=length/10.
3034
- ax.set_xlim(0-tol,length+tol)
3035
-
3036
- zmin=99999.
3037
- zmax=-99999.
3038
- nullvalue = -99999
3039
-
3040
- for curlabel, curarray in linked_arrays.items():
3041
- if curarray.plotted:
3042
-
3043
- ds = curarray.get_dxdy_min()
3044
-
3045
- nb = int(np.ceil(length/ds*2))
3046
-
3047
- alls = np.linspace(0,int(length),nb)
3048
-
3049
- pts = [myls.interpolate(curs) for curs in alls]
3050
-
3051
- allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
3052
-
3053
- zmaxloc=np.max(allz[allz!=nullvalue])
3054
- zminloc=np.min(allz[allz!=nullvalue])
3055
-
3056
- zmax=max(zmax,zmaxloc)
3057
- zmin=min(zmin,zminloc)
3058
-
3059
- if np.max(allz)>nullvalue:
3060
- # select parts
3061
- if nullvalue in allz:
3062
- # find all parts separated by nullvalue
3063
- nulls = np.argwhere(allz==nullvalue)
3064
- nulls = np.insert(nulls,0,-1)
3065
- nulls = np.append(nulls,len(allz))
3066
-
3067
- addlabel = True
3068
- for i in range(len(nulls)-1):
3069
- if nulls[i+1]-nulls[i]>1:
3070
- ax.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
3071
- color=colors[np.mod(k,3)],
3072
- lw=2.0,
3073
- label=curlabel if addlabel else None)
3074
- addlabel = False
3075
-
3076
- else:
3077
- ax.plot(alls,allz,
3078
- color=colors[np.mod(k,3)],
3079
- lw=2.0,
3080
- label=curlabel)
3081
- k+=1
3345
+ newvec.add_vertex(self.myvertices[k])
3082
3346
 
3083
- ax.set_ylim(zmin,zmax)
3084
- ax.legend()
3085
- ax.grid()
3086
- fig.canvas.draw()
3347
+ if [v2.x,v2.y,v2.z] != [newvec.myvertices[-1].x,newvec.myvertices[-1].y,newvec.myvertices[-1].z]:
3348
+ newvec.add_vertex(v2)
3087
3349
 
3088
- return fig,ax
3350
+ # if newvec.nbvertices==0:
3351
+ # a=1
3352
+ # if newvec.nbvertices==1:
3353
+ # a=1
3354
+ # newvec.update_lengths()
3355
+ # if np.min(newvec._lengthparts2D)==0.:
3356
+ # a=1
3357
+ return newvec
3089
3358
 
3090
- def plot_linked_wx(self, fig:MplFig, linked_arrays:dict):
3359
+ def get_values_linked_polygon(self, linked_arrays:list, getxy=False) -> dict:
3091
3360
  """
3092
- Graphique Matplolib de valeurs dans les matrices liées.
3361
+ Retourne les valeurs contenue dans le polygone
3093
3362
 
3094
- Version pour wxPython
3363
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3095
3364
  """
3365
+ vals={}
3096
3366
 
3097
- colors=['red','blue','green']
3098
-
3099
- exit=True
3100
- for curlabel, curarray in linked_arrays.items():
3367
+ for curarray in linked_arrays:
3101
3368
  if curarray.plotted:
3102
- exit=False
3103
-
3104
- if exit:
3105
- return
3369
+ vals[curarray.idx] = curarray.get_values_insidepoly(self, getxy=getxy)
3370
+ else:
3371
+ vals[curarray.idx] = None
3106
3372
 
3107
- k=0
3373
+ return vals
3108
3374
 
3109
- myls = self.asshapely_ls()
3110
- length = myls.length
3111
- tol=length/10.
3112
- fig.cur_ax.set_xlim(0-tol,length+tol)
3375
+ def get_all_values_linked_polygon(self, linked_arrays, getxy=False) -> dict:
3376
+ """
3377
+ Retourne toutes les valeurs contenue dans le polygone --> utile au moins pour les résultats WOLF2D
3113
3378
 
3114
- zmin=99999.
3115
- zmax=-99999.
3116
- nullvalue = -99999
3379
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3380
+ """
3381
+ vals={}
3117
3382
 
3118
- for curlabel, curarray in linked_arrays.items():
3383
+ for curarray in linked_arrays:
3119
3384
  if curarray.plotted:
3385
+ vals[curarray.idx] = curarray.get_all_values_insidepoly(self, getxy=getxy)
3386
+ else:
3387
+ vals[curarray.idx] = None
3120
3388
 
3121
- ds = curarray.get_dxdy_min()
3122
-
3123
- nb = int(np.ceil(length/ds*2))
3124
-
3125
- alls = np.linspace(0,int(length),nb)
3126
-
3127
- pts = [myls.interpolate(curs) for curs in alls]
3128
-
3129
- allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
3130
-
3131
- zmaxloc=np.max(allz[allz!=nullvalue])
3132
- zminloc=np.min(allz[allz!=nullvalue])
3389
+ return vals
3133
3390
 
3134
- zmax=max(zmax,zmaxloc)
3135
- zmin=min(zmin,zminloc)
3391
+ def get_all_values_linked_polyline(self,linked_arrays, getxy=True) -> dict:
3392
+ """
3393
+ Retourne toutes les valeurs sous la polyligne --> utile au moins pour les résultats WOLF2D
3136
3394
 
3137
- if np.max(allz)>nullvalue:
3138
- # select parts
3139
- if nullvalue in allz:
3140
- # find all parts separated by nullvalue
3141
- nulls = np.argwhere(allz==nullvalue)
3142
- nulls = np.insert(nulls,0,-1)
3143
- nulls = np.append(nulls,len(allz))
3395
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3396
+ """
3397
+ vals={}
3144
3398
 
3145
- addlabel = True
3146
- for i in range(len(nulls)-1):
3147
- if nulls[i+1]-nulls[i]>1:
3148
- fig.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
3149
- color=colors[np.mod(k,3)],
3150
- lw=2.0,
3151
- label=curlabel if addlabel else None)
3152
- addlabel = False
3399
+ for curarray in linked_arrays:
3400
+ if curarray.plotted:
3401
+ vals[curarray.idx], xy = curarray.get_all_values_underpoly(self, getxy=getxy)
3402
+ else:
3403
+ vals[curarray.idx] = None
3153
3404
 
3154
- else:
3155
- fig.plot(alls,allz,
3156
- color=colors[np.mod(k,3)],
3157
- lw=2.0,
3158
- label=curlabel)
3159
- k+=1
3405
+ return vals
3160
3406
 
3161
- fig.cur_ax.set_ylim(zmin,zmax)
3162
- fig.cur_ax.legend()
3163
- fig.cur_ax.grid()
3407
+ def get_values_on_vertices(self,curarray):
3408
+ """
3409
+ Récupération des valeurs sous les vertices et stockage dans la coordonnée 'z'
3410
+ """
3411
+ if not curarray.plotted:
3412
+ return
3164
3413
 
3165
- return fig
3414
+ for curpt in self.myvertices:
3415
+ curpt.z = curarray.get_value(curpt.x,curpt.y)
3166
3416
 
3167
- def plot_mpl(self,show=False,forceaspect=True,fig:Figure=None,ax:Axes=None,labels:dict={}):
3417
+ def get_values_linked(self, linked_arrays:dict, refine=True, filter_null = False):
3168
3418
  """
3169
- Graphique Matplolib du vecteur
3419
+ Récupération des valeurs dans les matrices liées sous les vertices et stockage dans la coordonnée 'z'
3420
+ Possibilité de raffiner la discrétisation pour obtenir au moins une valeur par maille
3170
3421
  """
3171
3422
 
3172
- x,y=self.get_sz()
3423
+ exit=True
3424
+ for curlabel, curarray in linked_arrays.items():
3425
+ if curarray.plotted:
3426
+ # at least one plotted array
3427
+ exit=False
3173
3428
 
3174
- xmin=x[0]
3175
- xmax=x[-1]
3176
- ymin=np.min(y)
3177
- ymax=np.max(y)
3429
+ if exit:
3430
+ return
3178
3431
 
3179
- if ax is None:
3180
- redraw=False
3181
- fig = plt.figure()
3182
- ax=fig.add_subplot(111)
3183
- else:
3184
- redraw=True
3185
- ax.cla()
3432
+ if refine:
3433
+ myzone=zone(name='linked_arrays - fine step')
3186
3434
 
3187
- if 'title' in labels.keys():
3188
- ax.set_title(labels['title'])
3189
- if 'xlabel' in labels.keys():
3190
- ax.set_xlabel(labels['xlabel'])
3191
- if 'ylabel' in labels.keys():
3192
- ax.set_ylabel(labels['ylabel'])
3435
+ for curlabel, curarray in linked_arrays.items():
3436
+ if curarray.plotted:
3193
3437
 
3194
- if ymax>-99999.:
3438
+ myvec=vector(name=curlabel,parentzone=myzone)
3439
+ myzone.add_vector(myvec)
3195
3440
 
3196
- dy=ymax-ymin
3197
- ymin-=dy/4.
3198
- ymax+=dy/4.
3441
+ ds = curarray.get_dxdy_min()
3199
3442
 
3200
- ax.plot(x,y,color='black',
3201
- lw=2.0,
3202
- label=self.myname)
3443
+ pts = self._refine2D(ds)
3203
3444
 
3204
- ax.legend()
3445
+ allz = [curarray.get_value(curpt.x, curpt.y, nullvalue=-99999) for curpt in pts]
3205
3446
 
3206
- tol=(xmax-xmin)/10.
3207
- ax.set_xlim(xmin-tol,xmax+tol)
3208
- ax.set_ylim(ymin,ymax)
3447
+ if filter_null:
3448
+ for curpt,curz in zip(pts,allz):
3449
+ if curz!=-99999:
3450
+ myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
3451
+ else:
3452
+ for curpt,curz in zip(pts,allz):
3453
+ myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
3209
3454
 
3210
- if forceaspect:
3211
- aspect=1.0*(ymax-ymin)/(xmax-xmin)*(ax.get_xlim()[1] - ax.get_xlim()[0]) / (ax.get_ylim()[1] - ax.get_ylim()[0])
3212
- ax.set_aspect(aspect)
3455
+ else:
3456
+ myzone=zone(name='linked_arrays')
3457
+ for curlabel, curarray in linked_arrays.items():
3458
+ if curarray.plotted:
3213
3459
 
3214
- if show:
3215
- fig.show()
3460
+ myvec=vector(name=curlabel,parentzone=myzone)
3461
+ myzone.add_vector(myvec)
3216
3462
 
3217
- if redraw:
3218
- fig.canvas.draw()
3463
+ if filter_null:
3464
+ for curpt in self.myvertices:
3465
+ locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3466
+ if locval !=-99999:
3467
+ myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3468
+ else:
3469
+ for curpt in self.myvertices:
3470
+ locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3471
+ myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3219
3472
 
3220
- return fig,ax
3473
+ return myzone
3221
3474
 
3222
3475
  def deepcopy_vector(self, name: str = None, parentzone = None) -> 'vector':
3223
3476
  """
@@ -3279,10 +3532,13 @@ class vector:
3279
3532
 
3280
3533
  def set_z(self, new_z:np.ndarray):
3281
3534
  """ Set the z values of the vertices """
3535
+ warnings.warn(_('This method is deprecated, use the z property instead.'), DeprecationWarning, stacklevel=2)
3536
+
3282
3537
  self.z = new_z
3283
3538
 
3284
3539
  @property
3285
3540
  def z(self):
3541
+ """ Return the z values of the vertices as a numpy array. """
3286
3542
  z = np.asarray([curvert.z for curvert in self.myvertices])
3287
3543
  if self.add_zdatum:
3288
3544
  z+=self.zdatum
@@ -3290,30 +3546,37 @@ class vector:
3290
3546
 
3291
3547
  @property
3292
3548
  def x(self):
3549
+ """ Return the x values of the vertices as a numpy array. """
3293
3550
  return np.asarray([curvert.x for curvert in self.myvertices])
3294
3551
 
3295
3552
  @property
3296
3553
  def y(self):
3554
+ """ Return the y values of the vertices as a numpy array. """
3297
3555
  return np.asarray([curvert.y for curvert in self.myvertices])
3298
3556
 
3299
3557
  @property
3300
3558
  def xy(self):
3559
+ """ Return the x, y values of the vertices as a 2D numpy array. """
3301
3560
  return np.asarray([[curvert.x, curvert.y] for curvert in self.myvertices])
3302
3561
 
3303
3562
  @property
3304
3563
  def xz(self):
3564
+ """ Return the x, z values of the vertices as a 2D numpy array. """
3305
3565
  return np.asarray([[curvert.x, curvert.z] for curvert in self.myvertices])
3306
3566
 
3307
3567
  @property
3308
3568
  def xyz(self):
3569
+ """ Return the x, y, z values of the vertices as a 3D numpy array. """
3309
3570
  return self.asnparray3d()
3310
3571
 
3311
3572
  @property
3312
3573
  def i(self):
3574
+ """ Return the in_use values of the vertices. """
3313
3575
  return np.asarray([curvert.in_use for curvert in self.myvertices])
3314
3576
 
3315
3577
  @property
3316
3578
  def xyzi(self):
3579
+ """ Return the x, y, z and in_use values of the vertices. """
3317
3580
  x = self.x
3318
3581
  y = self.y
3319
3582
  z = self.z
@@ -3322,20 +3585,27 @@ class vector:
3322
3585
 
3323
3586
  @property
3324
3587
  def xyi(self):
3588
+ """ Return the x, y and in_use values of the vertices. """
3325
3589
  return np.asarray([[curvert.x, curvert.y, curvert.in_use] for curvert in self.myvertices])
3326
3590
 
3327
3591
  @property
3328
3592
  def sz_curvi(self):
3593
+ """ Return the curvilinear abscissa and thz Z-value of the vector. """
3329
3594
  return self.get_sz()
3330
3595
 
3331
3596
  @property
3332
3597
  def s_curvi(self):
3598
+ """ Return the curvilinear abscissa of the vector. """
3333
3599
  sz = self.get_sz()
3334
3600
  return sz[0]
3335
3601
 
3336
3602
  @x.setter
3337
3603
  def x(self, new_x:np.ndarray | list):
3338
- """ Set the x values of the vertices """
3604
+ """ Set the x values of the vertices.
3605
+
3606
+ :param new_x: numpy array or list with x values - must have the same length as the number of vertices
3607
+ :type new_x: np.ndarray | list
3608
+ """
3339
3609
 
3340
3610
  if isinstance(new_x, list):
3341
3611
  new_x = np.array(new_x)
@@ -3352,7 +3622,11 @@ class vector:
3352
3622
 
3353
3623
  @y.setter
3354
3624
  def y(self, new_y:np.ndarray | list):
3355
- """ Set the y values of the vertices """
3625
+ """ Set the y values of the vertices.
3626
+
3627
+ :param new_y: numpy array or list with y values - must have the same length as the number of vertices
3628
+ :type new_y: np.ndarray | list
3629
+ """
3356
3630
 
3357
3631
  if isinstance(new_y, list):
3358
3632
  new_y = np.array(new_y)
@@ -3371,7 +3645,8 @@ class vector:
3371
3645
  def z(self, new_z:np.ndarray | float | list):
3372
3646
  """ Set the z values of the vertices
3373
3647
 
3374
- /PARAM new_z: numpy array, float or list (but WolfArray is supported too)
3648
+ :param new_z: numpy array, float or list (but WolfArray is supported too)
3649
+ :type new_z: np.ndarray | float | list | WolfArray
3375
3650
  """
3376
3651
  from .wolf_array import WolfArray
3377
3652
 
@@ -3405,7 +3680,11 @@ class vector:
3405
3680
 
3406
3681
  @xyz.setter
3407
3682
  def xyz(self, new_xyz:np.ndarray | list):
3408
- """ Set the x, y, z values of the vertices """
3683
+ """ Set the x, y, z values of the vertices.
3684
+
3685
+ :param new_xyz: numpy array or list with x, y, z values - must have the same length as the number of vertices
3686
+ :type new_xyz: np.ndarray | list
3687
+ """
3409
3688
 
3410
3689
  if isinstance(new_xyz, list):
3411
3690
  new_xyz = np.array(new_xyz)
@@ -3431,7 +3710,11 @@ class vector:
3431
3710
 
3432
3711
  @xy.setter
3433
3712
  def xy(self, new_xy:np.ndarray | list):
3434
- """ Set the x, y values of the vertices """
3713
+ """ Set the x, y values of the vertices.
3714
+
3715
+ :param new_xy: numpy array or list with x, y values - must have the same length as the number of vertices
3716
+ :type new_xy: np.ndarray | list
3717
+ """
3435
3718
 
3436
3719
  if isinstance(new_xy, list):
3437
3720
  new_xy = np.array(new_xy)
@@ -3449,7 +3732,11 @@ class vector:
3449
3732
 
3450
3733
  @xz.setter
3451
3734
  def xz(self, new_xz:np.ndarray | list):
3452
- """ Set the x, z values of the vertices """
3735
+ """ Set the x, z values of the vertices.
3736
+
3737
+ :param new_xz: numpy array or list with x, z values - must have the same length as the number of vertices
3738
+ :type new_xz: np.ndarray | list
3739
+ """
3453
3740
 
3454
3741
  if isinstance(new_xz, list):
3455
3742
  new_xz = np.array(new_xz)
@@ -3472,7 +3759,11 @@ class vector:
3472
3759
 
3473
3760
  @xyzi.setter
3474
3761
  def xyzi(self, new_xyzi:np.ndarray | list):
3475
- """ Set the x, y, z, in_use values of the vertices """
3762
+ """ Set the x, y, z, in_use values of the vertices.
3763
+
3764
+ :param new_xyzi: numpy array or list with x, y, z, in_use values - must have the same length as the number of vertices
3765
+ :type new_xyzi: np.ndarray | list
3766
+ """
3476
3767
 
3477
3768
  if isinstance(new_xyzi, list):
3478
3769
  new_xyzi = np.array(new_xyzi)
@@ -3492,7 +3783,11 @@ class vector:
3492
3783
 
3493
3784
  @xyi.setter
3494
3785
  def xyi(self, new_xyi:np.ndarray | list):
3495
- """ Set the x, y, in_use values of the vertices """
3786
+ """ Set the x, y, in_use values of the vertices.
3787
+
3788
+ :param new_xyi: numpy array or list with x, y, in_use values - must have the same length as the number of vertices
3789
+ :type new_xyi: np.ndarray | list
3790
+ """
3496
3791
 
3497
3792
  if isinstance(new_xyi, list):
3498
3793
  new_xyi = np.array(new_xyi)
@@ -3511,7 +3806,11 @@ class vector:
3511
3806
 
3512
3807
  @i.setter
3513
3808
  def i(self, new_i:np.ndarray | list):
3514
- """ Set the in_use values of the vertices """
3809
+ """ Set the in_use values of the vertices.
3810
+
3811
+ :param new_i: numpy array or list with in_use values - must have the same length as the number of vertices
3812
+ :type new_i: np.ndarray | list
3813
+ """
3515
3814
 
3516
3815
  if isinstance(new_i, list):
3517
3816
  new_i = np.array(new_i)
@@ -3528,7 +3827,11 @@ class vector:
3528
3827
 
3529
3828
  @sz_curvi.setter
3530
3829
  def sz_curvi(self, sz_new:np.ndarray | list):
3531
- """ Interpolate the vertices based on the curvilinear abscissa """
3830
+ """ Interpolate the vertice Z-coordinates based on a polyline defined as curvilinear abscissa and Z-value.
3831
+
3832
+ :param sz_new: numpy array or list with curvilinear abscissa and Z-value pairs
3833
+ :type sz_new: np.ndarray | list
3834
+ """
3532
3835
 
3533
3836
  if isinstance(sz_new, list):
3534
3837
  sz_new = np.array(sz_new)
@@ -3542,6 +3845,30 @@ class vector:
3542
3845
  self._reset_listogl()
3543
3846
  self.reset_linestring()
3544
3847
 
3848
+ @s_curvi.setter
3849
+ def s_curvi(self, new_s:np.ndarray | list):
3850
+ """ Replace the vertice XY-coordinates based on the curvilinear abscissa.
3851
+
3852
+ :param new_s: numpy array or list with curvilinear abscissa values - must have the same length as the number of vertices
3853
+ :type new_s: np.ndarray | list
3854
+ """
3855
+
3856
+ if isinstance(new_s, list):
3857
+ new_s = np.array(new_s)
3858
+
3859
+ if len(new_s) != self.nbvertices:
3860
+ logging.warning(_('New s values have not the same length as the number of vertices'))
3861
+ return
3862
+
3863
+ poly = self.linestring
3864
+
3865
+ for idx, curvert in enumerate(self.myvertices):
3866
+ curvert.x, curvert.y = poly.interpolate(new_s[idx]).xy
3867
+
3868
+ self._reset_listogl()
3869
+ self.reset_linestring()
3870
+
3871
+
3545
3872
  def __str__(self):
3546
3873
  return self.myname
3547
3874
 
@@ -3804,6 +4131,11 @@ class zone:
3804
4131
  # Object can be created from a shapely object
3805
4132
  self.import_shapelyobj(fromshapely)
3806
4133
 
4134
+ def check_if_interior_exists(self):
4135
+ """ Check if the zone has at least one vector with interior points """
4136
+ for curvec in self.myvectors:
4137
+ curvec.check_if_interior_exists()
4138
+
3807
4139
  def add_values(self, key:str, values:np.ndarray):
3808
4140
  """ add values to the zone """
3809
4141
 
@@ -4251,7 +4583,7 @@ class zone:
4251
4583
  for curvect in self.myvectors:
4252
4584
  curvect.plot_legend(sx, sy, xmin, ymin, xmax, ymax, size)
4253
4585
 
4254
- def plot_matplotlib(self, ax:plt.Axes):
4586
+ def plot_matplotlib(self, ax:plt.Axes | tuple[Figure, Axes] = None, **kwargs):
4255
4587
  """
4256
4588
  Plot the zone using matplotlib
4257
4589
 
@@ -4259,9 +4591,18 @@ class zone:
4259
4591
  :param kwargs: additional arguments
4260
4592
  """
4261
4593
 
4594
+ if isinstance(ax, tuple):
4595
+ fig, ax = ax
4596
+ elif ax is None:
4597
+ fig, ax = plt.subplots()
4598
+ else:
4599
+ fig = ax.figure
4600
+
4262
4601
  for curvect in self.myvectors:
4263
4602
  curvect.plot_matplotlib(ax)
4264
4603
 
4604
+ return fig, ax
4605
+
4265
4606
  def select_vectors_from_point(self,x:float,y:float,inside=True):
4266
4607
  """
4267
4608
  Sélection du vecteur de la zone sur base d'une coordonnée (x,y) -- en 2D
@@ -6160,6 +6501,11 @@ class Zones(wx.Frame, Element_To_Draw):
6160
6501
 
6161
6502
  return [curzone.myname for curzone in self.myzones]
6162
6503
 
6504
+ def check_if_interior_exists(self):
6505
+ """ Check if the zone has at least one vector with interior points """
6506
+ for curzone in self.myzones:
6507
+ curzone.check_if_interior_exists()
6508
+
6163
6509
  def add_values(self, key:str, values:np.ndarray | dict):
6164
6510
  """
6165
6511
  Add values to the zones
@@ -6660,7 +7006,7 @@ class Zones(wx.Frame, Element_To_Draw):
6660
7006
  curvect.myprop.color = curcolor
6661
7007
  curvect.myprop.alpha = 180
6662
7008
  curvect.myprop.transparent = True
6663
- curvect.myprop.filled = filled
7009
+ curvect.myprop.filled = filled and curvect.closed
6664
7010
 
6665
7011
  def set_width(self, width:int) -> None:
6666
7012
  """ Change with of all vectors in all zones """
@@ -6708,23 +7054,36 @@ class Zones(wx.Frame, Element_To_Draw):
6708
7054
 
6709
7055
  def import_dxf(self, fn, imported_elts=['POLYLINE','LWPOLYLINE','LINE']):
6710
7056
  """
6711
- Import d'un fichier DXF en tant qu'objets WOLF
7057
+ Import of a DXF file as a 'Zones'.
7058
+
7059
+ The DXF file is read and the elements are stored in zones based on their layers.
7060
+
7061
+ The supported elements are POLYLINE, LWPOLYLINE and LINE.
7062
+ If you want to import other elements, you must upgrade this routine `import_dxf`.
7063
+
7064
+ :param fn: name of the DXF file to import
7065
+ :param imported_elts: list of DXF elements to import. Default is ['POLYLINE','LWPOLYLINE','LINE'].
7066
+ :return: None
6712
7067
  """
6713
7068
  import ezdxf
6714
7069
 
6715
7070
  if not path.exists(fn):
6716
- try:
6717
- logging.warning(_('File not found !') + ' ' + fn)
6718
- except:
6719
- pass
7071
+ logging.warning(_('File not found !') + ' ' + fn)
6720
7072
  return
6721
7073
 
7074
+ for elt in imported_elts:
7075
+ assert elt in ['POLYLINE', 'LWPOLYLINE', 'LINE'], _('Unsupported DXF element: {}').format(elt)
7076
+
7077
+ self.is2D = False # we assume it's a 3D DXF
7078
+
6722
7079
  # Lecture du fichier dxf et identification du modelspace
6723
7080
  doc = ezdxf.readfile(fn)
6724
7081
  msp = doc.modelspace()
6725
- layers = doc.layers
7082
+ # layers = doc.layers
6726
7083
 
6727
7084
  used_layers = {}
7085
+ notloaded = {}
7086
+
6728
7087
  # Bouclage sur les éléments du DXF pour identifier les layers utiles et ensuite créer les zones adhoc
6729
7088
  for e in msp:
6730
7089
  if doc.layers.get(e.dxf.layer).is_on():
@@ -6750,14 +7109,23 @@ class Zones(wx.Frame, Element_To_Draw):
6750
7109
  curlayer = used_layers[e.dxf.layer]
6751
7110
  curlayer[e.dxftype().lower()]=0
6752
7111
  else:
6753
- logging.warning(_('DXF element not supported : ') + e.dxftype())
7112
+ if not e.dxftype() in notloaded.keys():
7113
+ notloaded[e.dxftype()] = 0
7114
+
7115
+ notloaded[e.dxftype()] += 1
7116
+ logging.debug(_('DXF element not supported : ') + e.dxftype())
6754
7117
  else:
6755
7118
  logging.info(_('Layer {} is off'.format(e.dxf.layer)))
6756
7119
 
7120
+ if len(notloaded)>0:
7121
+ logging.warning(_('Not loaded DXF elements : '))
7122
+ for curtype in notloaded.keys():
7123
+ logging.warning(_(' {} : {}'.format(curtype, notloaded[curtype])))
7124
+
6757
7125
  # Création des zones
6758
7126
  for curlayer in used_layers.keys():
6759
7127
  for curtype in used_layers[curlayer].keys():
6760
- curzone = used_layers[curlayer][curtype] = zone(name = '{} - {}'.format(curlayer,curtype),is2D=self.is2D,parent=self)
7128
+ curzone = used_layers[curlayer][curtype] = zone(name = '{} - {}'.format(curlayer,curtype), is2D=self.is2D, parent=self)
6761
7129
  self.add_zone(curzone)
6762
7130
 
6763
7131
  # Nouveau bouclage sur les éléments du DXF pour remplissage
@@ -6974,12 +7342,21 @@ class Zones(wx.Frame, Element_To_Draw):
6974
7342
  for curzone in self.myzones:
6975
7343
  curzone.plot(sx=sx, sy=sy, xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax, size=size)
6976
7344
 
6977
- def plot_matplotlib(self, ax:plt.Axes):
7345
+ def plot_matplotlib(self, ax:Axes | tuple[Figure, Axes] = None):
6978
7346
  """ Plot with matplotlib """
6979
7347
 
7348
+ if isinstance(ax, tuple):
7349
+ fig, ax = ax
7350
+ elif ax is None:
7351
+ fig, ax = plt.subplots()
7352
+ else:
7353
+ fig = ax.figure
7354
+
6980
7355
  for curzone in self.myzones:
6981
7356
  curzone.plot_matplotlib(ax)
6982
7357
 
7358
+ return fig, ax
7359
+
6983
7360
  def select_vectors_from_point(self, x:float, y:float, inside=True):
6984
7361
  """
6985
7362
  Sélection de vecteurs dans chaque zones sur base d'une coordonnée
@@ -7070,6 +7447,10 @@ class Zones(wx.Frame, Element_To_Draw):
7070
7447
  self.updatevertices.SetToolTip(_("Transfer the coordinates from the editor to the memory and update the plot"))
7071
7448
  self.updatevertices.Bind(wx.EVT_BUTTON,self.Onupdatevertices)
7072
7449
 
7450
+ self._test_interior = wx.Button(self,label=_('Test interior'))
7451
+ self._test_interior.SetToolTip(_("Test if some segments of the active vector are exactly the same"))
7452
+ self._test_interior.Bind(wx.EVT_BUTTON,self.Ontest_interior)
7453
+
7073
7454
  self.plot_mpl = wx.Button(self,label=_('Plot xy'))
7074
7455
  self.plot_mpl.SetToolTip(_("Plot the active vector in a new window (matplotlib)"))
7075
7456
  self.plot_mpl.Bind(wx.EVT_BUTTON,self.Onplotmpl)
@@ -7079,7 +7460,7 @@ class Zones(wx.Frame, Element_To_Draw):
7079
7460
  self.plot_mplsz.Bind(wx.EVT_BUTTON,self.Onplotmplsz)
7080
7461
 
7081
7462
  sizer_add_update.Add(self.addrows,1, wx.EXPAND)
7082
- sizer_add_update.Add(self.updatevertices,3, wx.EXPAND)
7463
+ sizer_add_update.Add(self.updatevertices, 1, wx.EXPAND)
7083
7464
  sizer_add_update.Add(self.plot_mpl,1, wx.EXPAND)
7084
7465
  sizer_add_update.Add(self.plot_mplsz,1, wx.EXPAND)
7085
7466
 
@@ -7235,6 +7616,8 @@ class Zones(wx.Frame, Element_To_Draw):
7235
7616
 
7236
7617
  box_interp_indices = wx.BoxSizer(wx.HORIZONTAL)
7237
7618
  box_interp_indices.Add(self.interpxyz,1,wx.EXPAND)
7619
+ box_interp_indices.Add(self._test_interior, 1, wx.EXPAND)
7620
+
7238
7621
 
7239
7622
  boxright.Add(box_interp_indices,0,wx.EXPAND)
7240
7623
 
@@ -7410,7 +7793,7 @@ class Zones(wx.Frame, Element_To_Draw):
7410
7793
  self.fill_structure()
7411
7794
 
7412
7795
  self.treelist.SetSize(200,500)
7413
- self.SetSize(600,700)
7796
+ self.SetSize(650,700)
7414
7797
 
7415
7798
  self.SetSizer(box)
7416
7799
 
@@ -8781,6 +9164,18 @@ class Zones(wx.Frame, Element_To_Draw):
8781
9164
  self.active_vector.updatefromgrid(self.xls)
8782
9165
  self.find_minmax(True)
8783
9166
 
9167
+ def Ontest_interior(self, event:wx.MouseEvent):
9168
+ """ Test if the active vector has interior portions """
9169
+ if self.verify_activevec():
9170
+ return
9171
+
9172
+ self.active_vector.check_if_interior_exists()
9173
+
9174
+ self.active_vector._fillgrid_only_i(self.xls)
9175
+
9176
+ self.get_mapviewer().Paint()
9177
+
9178
+
8784
9179
  def Onplotmpl(self, event:wx.MouseEvent):
8785
9180
  """
8786
9181
  Plot active vector in matplotlib