wolfhece 2.2.34__py3-none-any.whl → 2.2.36__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,44 @@ class vector:
2212
2276
 
2213
2277
  return len(not_in_use) > 0
2214
2278
 
2279
+ @property
2280
+ def nb_interiors(self) -> int:
2281
+ """ Return the number of interiors in the vector.
2282
+
2283
+ If the vector is filled, it returns the number of pairs of vertices not in use.
2284
+ If the vector is not filled, it returns the number of vertices not in use.
2285
+ """
2286
+ not_in_use = [curvert for curvert in self.myvertices if not curvert.in_use]
2287
+
2288
+ return len(not_in_use) // 2 if self.myprop.filled else len(not_in_use)
2289
+
2290
+ @property
2291
+ def _parts(self) -> "zone":
2292
+ """ Return the parts of the vector as a zone.
2293
+
2294
+ Useful for creating subpolygons or triangulation.
2295
+ """
2296
+ self.find_minmax()
2297
+
2298
+ parts = zone()
2299
+ current_part = vector()
2300
+ for curvert in self.myvertices:
2301
+ if curvert.in_use:
2302
+ current_part.add_vertex(curvert)
2303
+ else:
2304
+ if current_part.nbvertices > 0:
2305
+ if parts.nbvectors > 0:
2306
+ current_part.force_to_close()
2307
+ parts.add_vector(current_part)
2308
+ current_part = vector()
2309
+
2310
+ for curvert in current_part.myvertices:
2311
+ parts.myvectors[0].add_vertex(curvert)
2312
+
2313
+ parts.myvectors[0].force_to_close()
2314
+
2315
+ return parts
2316
+
2215
2317
  def get_subpolygons(self) -> list[list[wolfvertex]]:
2216
2318
  """
2217
2319
  Return a list of polygons from the vector
@@ -2223,10 +2325,21 @@ class vector:
2223
2325
  return []
2224
2326
 
2225
2327
  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]]]
2328
+ if self.has_interior:
2329
+ #En attendant de lier WOLF-Fortran, on utilise la triangulation contrainte de la librairie Triangle -- https://rufat.be/triangle/
2330
+
2331
+ parts = self._parts
2332
+ tri = parts.create_constrainedDelaunay(nb = 0)
2333
+ centroid_interiors = [part.centroid for part in parts.myvectors[1:]]
2334
+ tri.unuse_triangles_containing_points(centroid_interiors)
2335
+
2336
+ return tri.get_triangles_as_listwolfvertices()
2337
+
2228
2338
  else:
2229
- return [self.myvertices]
2339
+ if self.myprop.closed and (self.myvertices[0].x != self.myvertices[-1].x or self.myvertices[0].y != self.myvertices[-1].y):
2340
+ return [self.myvertices + [self.myvertices[0]]]
2341
+ else:
2342
+ return [self.myvertices]
2230
2343
 
2231
2344
  else:
2232
2345
  if self.has_interior:
@@ -2488,19 +2601,32 @@ class vector:
2488
2601
  else:
2489
2602
  logging.warning(_('No image texture available for plot'))
2490
2603
 
2491
- def plot_matplotlib(self, ax:plt.Axes):
2604
+ def plot_matplotlib(self, ax:plt.Axes | tuple[Figure, Axes] = None):
2492
2605
  """
2493
- Plot Matplotlib
2606
+ Plot Matplotlib - XY coordinates ONLY
2607
+
2608
+ :param ax: Matplotlib Axes to plot on or a tuple (fig, ax) where fig is the figure and ax is the axes.
2609
+ If ax is None, a new figure and axes will be created.
2494
2610
  """
2495
2611
 
2612
+ if isinstance(ax, tuple):
2613
+ # if ax is a tuple, we assume it is (fig, ax)
2614
+ fig, ax = ax
2615
+ elif ax is None:
2616
+ fig, ax = plt.subplots()
2617
+ else:
2618
+ fig = ax.figure
2619
+
2496
2620
  if self.myprop.used:
2497
2621
 
2498
2622
  if self.myprop.filled:
2499
2623
  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.))
2624
+ subpoly = self.get_subpolygons()
2625
+ for curpoly in subpoly:
2626
+ if self.myprop.transparent:
2627
+ 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))
2628
+ else:
2629
+ 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
2630
  else:
2505
2631
  rgb=getRGBfromI(self.myprop.color)
2506
2632
  subpoly = self.get_subpolygons()
@@ -2512,6 +2638,258 @@ class vector:
2512
2638
 
2513
2639
  self.plot_legend_mpl(ax)
2514
2640
 
2641
+ return fig, ax
2642
+
2643
+ def plot_matplotlib_sz(self, ax:plt.Axes | tuple[Figure, Axes] = None):
2644
+ """
2645
+ Plot Matplotlib - SZ coordinates ONLY.
2646
+
2647
+ S is the curvilinear abscissa, Z is the elevation.
2648
+
2649
+ :param ax: Matplotlib Axes to plot on or a tuple (fig, ax) where fig is the figure and ax is the axes.
2650
+ If ax is None, a new figure and axes will be created.
2651
+ """
2652
+
2653
+ if isinstance(ax, tuple):
2654
+ # if ax is a tuple, we assume it is (fig, ax)
2655
+ fig, ax = ax
2656
+ elif ax is None:
2657
+ fig, ax = plt.subplots()
2658
+ else:
2659
+ fig = ax.figure
2660
+
2661
+ if self.myprop.used:
2662
+ s,z = self.sz_curvi
2663
+
2664
+ rgb=getRGBfromI(self.myprop.color)
2665
+ if self.myprop.transparent:
2666
+ ax.plot(s, z, color=(rgb[0]/255., rgb[1]/255., rgb[2]/255., self.myprop.alpha), linewidth=self.myprop.width)
2667
+ else:
2668
+ ax.plot(s, z, color=(rgb[0]/255., rgb[1]/255., rgb[2]/255.), linewidth=self.myprop.width)
2669
+
2670
+ return fig, ax
2671
+
2672
+ def plot_linked(self, fig, ax, linked_arrays:dict):
2673
+ """
2674
+ Graphique Matplolib de valeurs dans les matrices liées
2675
+ """
2676
+ # from .wolf_array import WolfArray
2677
+ # from .wolfresults_2D import Wolfresults_2D
2678
+
2679
+ colors=['red','blue','green']
2680
+
2681
+ exit=True
2682
+ for curlabel, curarray in linked_arrays.items():
2683
+ if curarray.plotted:
2684
+ exit=False
2685
+
2686
+ if exit:
2687
+ logging.warning(_('No plotted linked arrays'))
2688
+ return
2689
+
2690
+ k=0
2691
+
2692
+ myls = self.asshapely_ls()
2693
+ length = myls.length
2694
+ tol=length/10.
2695
+ ax.set_xlim(0-tol,length+tol)
2696
+
2697
+ zmin=99999.
2698
+ zmax=-99999.
2699
+ nullvalue = -99999
2700
+
2701
+ for curlabel, curarray in linked_arrays.items():
2702
+ if curarray.plotted:
2703
+
2704
+ ds = curarray.get_dxdy_min()
2705
+
2706
+ nb = int(np.ceil(length/ds*2))
2707
+
2708
+ alls = np.linspace(0,int(length),nb)
2709
+
2710
+ pts = [myls.interpolate(curs) for curs in alls]
2711
+
2712
+ allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
2713
+
2714
+ zmaxloc=np.max(allz[allz!=nullvalue])
2715
+ zminloc=np.min(allz[allz!=nullvalue])
2716
+
2717
+ zmax=max(zmax,zmaxloc)
2718
+ zmin=min(zmin,zminloc)
2719
+
2720
+ if np.max(allz)>nullvalue:
2721
+ # select parts
2722
+ if nullvalue in allz:
2723
+ # find all parts separated by nullvalue
2724
+ nulls = np.argwhere(allz==nullvalue)
2725
+ nulls = np.insert(nulls,0,-1)
2726
+ nulls = np.append(nulls,len(allz))
2727
+
2728
+ addlabel = True
2729
+ for i in range(len(nulls)-1):
2730
+ if nulls[i+1]-nulls[i]>1:
2731
+ ax.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
2732
+ color=colors[np.mod(k,3)],
2733
+ lw=2.0,
2734
+ label=curlabel if addlabel else None)
2735
+ addlabel = False
2736
+
2737
+ else:
2738
+ ax.plot(alls,allz,
2739
+ color=colors[np.mod(k,3)],
2740
+ lw=2.0,
2741
+ label=curlabel)
2742
+ k+=1
2743
+
2744
+ ax.set_ylim(zmin,zmax)
2745
+ ax.legend()
2746
+ ax.grid()
2747
+ fig.canvas.draw()
2748
+
2749
+ return fig,ax
2750
+
2751
+ def plot_linked_wx(self, fig:MplFig, linked_arrays:dict):
2752
+ """
2753
+ Graphique Matplolib de valeurs dans les matrices liées.
2754
+
2755
+ Version pour wxPython
2756
+ """
2757
+
2758
+ colors=['red','blue','green']
2759
+
2760
+ exit=True
2761
+ for curlabel, curarray in linked_arrays.items():
2762
+ if curarray.plotted:
2763
+ exit=False
2764
+
2765
+ if exit:
2766
+ return
2767
+
2768
+ k=0
2769
+
2770
+ myls = self.asshapely_ls()
2771
+ length = myls.length
2772
+ tol=length/10.
2773
+ fig.cur_ax.set_xlim(0-tol,length+tol)
2774
+
2775
+ zmin=99999.
2776
+ zmax=-99999.
2777
+ nullvalue = -99999
2778
+
2779
+ for curlabel, curarray in linked_arrays.items():
2780
+ if curarray.plotted:
2781
+
2782
+ ds = curarray.get_dxdy_min()
2783
+
2784
+ nb = int(np.ceil(length/ds*2))
2785
+
2786
+ alls = np.linspace(0,int(length),nb)
2787
+
2788
+ pts = [myls.interpolate(curs) for curs in alls]
2789
+
2790
+ allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
2791
+
2792
+ zmaxloc=np.max(allz[allz!=nullvalue])
2793
+ zminloc=np.min(allz[allz!=nullvalue])
2794
+
2795
+ zmax=max(zmax,zmaxloc)
2796
+ zmin=min(zmin,zminloc)
2797
+
2798
+ if np.max(allz)>nullvalue:
2799
+ # select parts
2800
+ if nullvalue in allz:
2801
+ # find all parts separated by nullvalue
2802
+ nulls = np.argwhere(allz==nullvalue)
2803
+ nulls = np.insert(nulls,0,-1)
2804
+ nulls = np.append(nulls,len(allz))
2805
+
2806
+ addlabel = True
2807
+ for i in range(len(nulls)-1):
2808
+ if nulls[i+1]-nulls[i]>1:
2809
+ fig.plot(alls[nulls[i]+1:nulls[i+1]],allz[nulls[i]+1:nulls[i+1]],
2810
+ color=colors[np.mod(k,3)],
2811
+ lw=2.0,
2812
+ label=curlabel if addlabel else None)
2813
+ addlabel = False
2814
+
2815
+ else:
2816
+ fig.plot(alls,allz,
2817
+ color=colors[np.mod(k,3)],
2818
+ lw=2.0,
2819
+ label=curlabel)
2820
+ k+=1
2821
+
2822
+ fig.cur_ax.set_ylim(zmin,zmax)
2823
+ fig.cur_ax.legend()
2824
+ fig.cur_ax.grid()
2825
+
2826
+ return fig
2827
+
2828
+ def plot_mpl(self, show=False,
2829
+ forceaspect=True,
2830
+ fig:Figure=None,
2831
+ ax:Axes=None,
2832
+ labels:dict={},
2833
+ clear_ax:bool =True):
2834
+ """
2835
+ Graphique Matplolib du vecteur - SZ coordinates ONLY
2836
+
2837
+ DEPRECATED: Use plot_matplotlib_sz instead.
2838
+ """
2839
+ warnings.warn("plot_mpl is deprecated, use plot_matplotlib_sz instead", DeprecationWarning, stacklevel=2)
2840
+
2841
+ x,y=self.get_sz()
2842
+
2843
+ xmin=x[0]
2844
+ xmax=x[-1]
2845
+ ymin=np.min(y)
2846
+ ymax=np.max(y)
2847
+
2848
+ if ax is None:
2849
+ redraw=False
2850
+ fig = plt.figure()
2851
+ ax=fig.add_subplot(111)
2852
+ else:
2853
+ redraw=True
2854
+ if clear_ax:
2855
+ # Clear the axes if specified
2856
+ ax.cla()
2857
+
2858
+ if 'title' in labels.keys():
2859
+ ax.set_title(labels['title'])
2860
+ if 'xlabel' in labels.keys():
2861
+ ax.set_xlabel(labels['xlabel'])
2862
+ if 'ylabel' in labels.keys():
2863
+ ax.set_ylabel(labels['ylabel'])
2864
+
2865
+ if ymax>-99999.:
2866
+
2867
+ dy=ymax-ymin
2868
+ ymin-=dy/4.
2869
+ ymax+=dy/4.
2870
+
2871
+ ax.plot(x,y,color='black',
2872
+ lw=2.0,
2873
+ label=self.myname)
2874
+
2875
+ ax.legend()
2876
+
2877
+ tol=(xmax-xmin)/10.
2878
+ ax.set_xlim(xmin-tol,xmax+tol)
2879
+ ax.set_ylim(ymin,ymax)
2880
+
2881
+ if forceaspect:
2882
+ aspect=1.0*(ymax-ymin)/(xmax-xmin)*(ax.get_xlim()[1] - ax.get_xlim()[0]) / (ax.get_ylim()[1] - ax.get_ylim()[0])
2883
+ ax.set_aspect(aspect)
2884
+
2885
+ if show:
2886
+ fig.show()
2887
+
2888
+ if redraw:
2889
+ fig.canvas.draw()
2890
+
2891
+ return fig,ax
2892
+
2515
2893
  def _get_textfont(self):
2516
2894
  """ Retunr a 'Text_Infos' instance for the legend """
2517
2895
 
@@ -2789,7 +3167,7 @@ class vector:
2789
3167
 
2790
3168
  return pts
2791
3169
 
2792
- def split(self,ds, new=True):
3170
+ def split(self, ds, new=True):
2793
3171
  """
2794
3172
  Création d'un nouveau vecteur sur base du découpage d'un autre et d'un pas spatial à respecter
2795
3173
  Le nouveau vecteur contient tous les points de l'ancien et des nouveaux sur base d'un découpage 3D
@@ -2854,370 +3232,159 @@ class vector:
2854
3232
  self.myvertices[k1].z*pond1+self.myvertices[k1+1].z*(1.-pond1))
2855
3233
 
2856
3234
  v2= wolfvertex(self.myvertices[k2].x*pond2+self.myvertices[k2+1].x*(1.-pond2),
2857
- self.myvertices[k2].y*pond2+self.myvertices[k2+1].y*(1.-pond2),
2858
- self.myvertices[k2].z*pond2+self.myvertices[k2+1].z*(1.-pond2))
2859
-
2860
- newvec = vector(name='substr')
2861
-
2862
- newvec.add_vertex(v1)
2863
-
2864
- if s1<=s2:
2865
- if is3D:
2866
- for k in range(k1+1,k2+1):
2867
- if self.myvertices[k].dist3D(newvec.myvertices[-1])!=0.:
2868
- newvec.add_vertex(self.myvertices[k])
2869
- else:
2870
- for k in range(k1+1,k2+1):
2871
- if self.myvertices[k].dist2D(newvec.myvertices[-1])!=0.:
2872
- newvec.add_vertex(self.myvertices[k])
2873
- else:
2874
- if is3D:
2875
- for k in range(k1+1,k2+1,-1):
2876
- if self.myvertices[k].dist3D(newvec.myvertices[-1])!=0.:
2877
- newvec.add_vertex(self.myvertices[k])
2878
- else:
2879
- for k in range(k1+1,k2+1,-1):
2880
- 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
3082
-
3083
- ax.set_ylim(zmin,zmax)
3084
- ax.legend()
3085
- ax.grid()
3086
- fig.canvas.draw()
3087
-
3088
- return fig,ax
3089
-
3090
- def plot_linked_wx(self, fig:MplFig, linked_arrays:dict):
3091
- """
3092
- Graphique Matplolib de valeurs dans les matrices liées.
3235
+ self.myvertices[k2].y*pond2+self.myvertices[k2+1].y*(1.-pond2),
3236
+ self.myvertices[k2].z*pond2+self.myvertices[k2+1].z*(1.-pond2))
3093
3237
 
3094
- Version pour wxPython
3095
- """
3238
+ newvec = vector(name='substr')
3096
3239
 
3097
- colors=['red','blue','green']
3240
+ newvec.add_vertex(v1)
3098
3241
 
3099
- exit=True
3100
- for curlabel, curarray in linked_arrays.items():
3101
- if curarray.plotted:
3102
- exit=False
3242
+ if s1<=s2:
3243
+ if is3D:
3244
+ for k in range(k1+1,k2+1):
3245
+ if self.myvertices[k].dist3D(newvec.myvertices[-1])!=0.:
3246
+ newvec.add_vertex(self.myvertices[k])
3247
+ else:
3248
+ for k in range(k1+1,k2+1):
3249
+ if self.myvertices[k].dist2D(newvec.myvertices[-1])!=0.:
3250
+ newvec.add_vertex(self.myvertices[k])
3251
+ else:
3252
+ if is3D:
3253
+ for k in range(k1+1,k2+1,-1):
3254
+ if self.myvertices[k].dist3D(newvec.myvertices[-1])!=0.:
3255
+ newvec.add_vertex(self.myvertices[k])
3256
+ else:
3257
+ for k in range(k1+1,k2+1,-1):
3258
+ if self.myvertices[k].dist2D(newvec.myvertices[-1])!=0.:
3259
+ newvec.add_vertex(self.myvertices[k])
3103
3260
 
3104
- if exit:
3105
- return
3261
+ if [v2.x,v2.y,v2.z] != [newvec.myvertices[-1].x,newvec.myvertices[-1].y,newvec.myvertices[-1].z]:
3262
+ newvec.add_vertex(v2)
3106
3263
 
3107
- k=0
3264
+ # if newvec.nbvertices==0:
3265
+ # a=1
3266
+ # if newvec.nbvertices==1:
3267
+ # a=1
3268
+ # newvec.update_lengths()
3269
+ # if np.min(newvec._lengthparts2D)==0.:
3270
+ # a=1
3271
+ return newvec
3108
3272
 
3109
- myls = self.asshapely_ls()
3110
- length = myls.length
3111
- tol=length/10.
3112
- fig.cur_ax.set_xlim(0-tol,length+tol)
3273
+ def get_values_linked_polygon(self, linked_arrays:list, getxy=False) -> dict:
3274
+ """
3275
+ Retourne les valeurs contenue dans le polygone
3113
3276
 
3114
- zmin=99999.
3115
- zmax=-99999.
3116
- nullvalue = -99999
3277
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3278
+ """
3279
+ vals={}
3117
3280
 
3118
- for curlabel, curarray in linked_arrays.items():
3281
+ for curarray in linked_arrays:
3119
3282
  if curarray.plotted:
3283
+ vals[curarray.idx] = curarray.get_values_insidepoly(self, getxy=getxy)
3284
+ else:
3285
+ vals[curarray.idx] = None
3120
3286
 
3121
- ds = curarray.get_dxdy_min()
3122
-
3123
- nb = int(np.ceil(length/ds*2))
3287
+ return vals
3124
3288
 
3125
- alls = np.linspace(0,int(length),nb)
3289
+ def get_all_values_linked_polygon(self, linked_arrays, getxy=False) -> dict:
3290
+ """
3291
+ Retourne toutes les valeurs contenue dans le polygone --> utile au moins pour les résultats WOLF2D
3126
3292
 
3127
- pts = [myls.interpolate(curs) for curs in alls]
3293
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3294
+ """
3295
+ vals={}
3128
3296
 
3129
- allz = np.asarray([curarray.get_value(curpt.x,curpt.y, nullvalue= nullvalue) for curpt in pts])
3297
+ for curarray in linked_arrays:
3298
+ if curarray.plotted:
3299
+ vals[curarray.idx] = curarray.get_all_values_insidepoly(self, getxy=getxy)
3300
+ else:
3301
+ vals[curarray.idx] = None
3130
3302
 
3131
- zmaxloc=np.max(allz[allz!=nullvalue])
3132
- zminloc=np.min(allz[allz!=nullvalue])
3303
+ return vals
3133
3304
 
3134
- zmax=max(zmax,zmaxloc)
3135
- zmin=min(zmin,zminloc)
3305
+ def get_all_values_linked_polyline(self,linked_arrays, getxy=True) -> dict:
3306
+ """
3307
+ Retourne toutes les valeurs sous la polyligne --> utile au moins pour les résultats WOLF2D
3136
3308
 
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))
3309
+ linked_arrays : liste Python d'objet matriciels WolfArray (ou surcharge)
3310
+ """
3311
+ vals={}
3144
3312
 
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
3313
+ for curarray in linked_arrays:
3314
+ if curarray.plotted:
3315
+ vals[curarray.idx], xy = curarray.get_all_values_underpoly(self, getxy=getxy)
3316
+ else:
3317
+ vals[curarray.idx] = None
3153
3318
 
3154
- else:
3155
- fig.plot(alls,allz,
3156
- color=colors[np.mod(k,3)],
3157
- lw=2.0,
3158
- label=curlabel)
3159
- k+=1
3319
+ return vals
3160
3320
 
3161
- fig.cur_ax.set_ylim(zmin,zmax)
3162
- fig.cur_ax.legend()
3163
- fig.cur_ax.grid()
3321
+ def get_values_on_vertices(self,curarray):
3322
+ """
3323
+ Récupération des valeurs sous les vertices et stockage dans la coordonnée 'z'
3324
+ """
3325
+ if not curarray.plotted:
3326
+ return
3164
3327
 
3165
- return fig
3328
+ for curpt in self.myvertices:
3329
+ curpt.z = curarray.get_value(curpt.x,curpt.y)
3166
3330
 
3167
- def plot_mpl(self,show=False,forceaspect=True,fig:Figure=None,ax:Axes=None,labels:dict={}):
3331
+ def get_values_linked(self, linked_arrays:dict, refine=True, filter_null = False):
3168
3332
  """
3169
- Graphique Matplolib du vecteur
3333
+ Récupération des valeurs dans les matrices liées sous les vertices et stockage dans la coordonnée 'z'
3334
+ Possibilité de raffiner la discrétisation pour obtenir au moins une valeur par maille
3170
3335
  """
3171
3336
 
3172
- x,y=self.get_sz()
3337
+ exit=True
3338
+ for curlabel, curarray in linked_arrays.items():
3339
+ if curarray.plotted:
3340
+ # at least one plotted array
3341
+ exit=False
3173
3342
 
3174
- xmin=x[0]
3175
- xmax=x[-1]
3176
- ymin=np.min(y)
3177
- ymax=np.max(y)
3343
+ if exit:
3344
+ return
3178
3345
 
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()
3346
+ if refine:
3347
+ myzone=zone(name='linked_arrays - fine step')
3186
3348
 
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'])
3349
+ for curlabel, curarray in linked_arrays.items():
3350
+ if curarray.plotted:
3193
3351
 
3194
- if ymax>-99999.:
3352
+ myvec=vector(name=curlabel,parentzone=myzone)
3353
+ myzone.add_vector(myvec)
3195
3354
 
3196
- dy=ymax-ymin
3197
- ymin-=dy/4.
3198
- ymax+=dy/4.
3355
+ ds = curarray.get_dxdy_min()
3199
3356
 
3200
- ax.plot(x,y,color='black',
3201
- lw=2.0,
3202
- label=self.myname)
3357
+ pts = self._refine2D(ds)
3203
3358
 
3204
- ax.legend()
3359
+ allz = [curarray.get_value(curpt.x, curpt.y, nullvalue=-99999) for curpt in pts]
3205
3360
 
3206
- tol=(xmax-xmin)/10.
3207
- ax.set_xlim(xmin-tol,xmax+tol)
3208
- ax.set_ylim(ymin,ymax)
3361
+ if filter_null:
3362
+ for curpt,curz in zip(pts,allz):
3363
+ if curz!=-99999:
3364
+ myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
3365
+ else:
3366
+ for curpt,curz in zip(pts,allz):
3367
+ myvec.add_vertex(wolfvertex(curpt.x,curpt.y,curz))
3209
3368
 
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)
3369
+ else:
3370
+ myzone=zone(name='linked_arrays')
3371
+ for curlabel, curarray in linked_arrays.items():
3372
+ if curarray.plotted:
3213
3373
 
3214
- if show:
3215
- fig.show()
3374
+ myvec=vector(name=curlabel,parentzone=myzone)
3375
+ myzone.add_vector(myvec)
3216
3376
 
3217
- if redraw:
3218
- fig.canvas.draw()
3377
+ if filter_null:
3378
+ for curpt in self.myvertices:
3379
+ locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3380
+ if locval !=-99999:
3381
+ myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3382
+ else:
3383
+ for curpt in self.myvertices:
3384
+ locval = curarray.get_value(curpt.x, curpt.y, nullvalue=-99999)
3385
+ myvec.add_vertex(wolfvertex(curpt.x, curpt.y, locval))
3219
3386
 
3220
- return fig,ax
3387
+ return myzone
3221
3388
 
3222
3389
  def deepcopy_vector(self, name: str = None, parentzone = None) -> 'vector':
3223
3390
  """
@@ -3279,10 +3446,13 @@ class vector:
3279
3446
 
3280
3447
  def set_z(self, new_z:np.ndarray):
3281
3448
  """ Set the z values of the vertices """
3449
+ warnings.warn(_('This method is deprecated, use the z property instead.'), DeprecationWarning, stacklevel=2)
3450
+
3282
3451
  self.z = new_z
3283
3452
 
3284
3453
  @property
3285
3454
  def z(self):
3455
+ """ Return the z values of the vertices as a numpy array. """
3286
3456
  z = np.asarray([curvert.z for curvert in self.myvertices])
3287
3457
  if self.add_zdatum:
3288
3458
  z+=self.zdatum
@@ -3290,30 +3460,37 @@ class vector:
3290
3460
 
3291
3461
  @property
3292
3462
  def x(self):
3463
+ """ Return the x values of the vertices as a numpy array. """
3293
3464
  return np.asarray([curvert.x for curvert in self.myvertices])
3294
3465
 
3295
3466
  @property
3296
3467
  def y(self):
3468
+ """ Return the y values of the vertices as a numpy array. """
3297
3469
  return np.asarray([curvert.y for curvert in self.myvertices])
3298
3470
 
3299
3471
  @property
3300
3472
  def xy(self):
3473
+ """ Return the x, y values of the vertices as a 2D numpy array. """
3301
3474
  return np.asarray([[curvert.x, curvert.y] for curvert in self.myvertices])
3302
3475
 
3303
3476
  @property
3304
3477
  def xz(self):
3478
+ """ Return the x, z values of the vertices as a 2D numpy array. """
3305
3479
  return np.asarray([[curvert.x, curvert.z] for curvert in self.myvertices])
3306
3480
 
3307
3481
  @property
3308
3482
  def xyz(self):
3483
+ """ Return the x, y, z values of the vertices as a 3D numpy array. """
3309
3484
  return self.asnparray3d()
3310
3485
 
3311
3486
  @property
3312
3487
  def i(self):
3488
+ """ Return the in_use values of the vertices. """
3313
3489
  return np.asarray([curvert.in_use for curvert in self.myvertices])
3314
3490
 
3315
3491
  @property
3316
3492
  def xyzi(self):
3493
+ """ Return the x, y, z and in_use values of the vertices. """
3317
3494
  x = self.x
3318
3495
  y = self.y
3319
3496
  z = self.z
@@ -3322,20 +3499,27 @@ class vector:
3322
3499
 
3323
3500
  @property
3324
3501
  def xyi(self):
3502
+ """ Return the x, y and in_use values of the vertices. """
3325
3503
  return np.asarray([[curvert.x, curvert.y, curvert.in_use] for curvert in self.myvertices])
3326
3504
 
3327
3505
  @property
3328
3506
  def sz_curvi(self):
3507
+ """ Return the curvilinear abscissa and thz Z-value of the vector. """
3329
3508
  return self.get_sz()
3330
3509
 
3331
3510
  @property
3332
3511
  def s_curvi(self):
3512
+ """ Return the curvilinear abscissa of the vector. """
3333
3513
  sz = self.get_sz()
3334
3514
  return sz[0]
3335
3515
 
3336
3516
  @x.setter
3337
3517
  def x(self, new_x:np.ndarray | list):
3338
- """ Set the x values of the vertices """
3518
+ """ Set the x values of the vertices.
3519
+
3520
+ :param new_x: numpy array or list with x values - must have the same length as the number of vertices
3521
+ :type new_x: np.ndarray | list
3522
+ """
3339
3523
 
3340
3524
  if isinstance(new_x, list):
3341
3525
  new_x = np.array(new_x)
@@ -3352,7 +3536,11 @@ class vector:
3352
3536
 
3353
3537
  @y.setter
3354
3538
  def y(self, new_y:np.ndarray | list):
3355
- """ Set the y values of the vertices """
3539
+ """ Set the y values of the vertices.
3540
+
3541
+ :param new_y: numpy array or list with y values - must have the same length as the number of vertices
3542
+ :type new_y: np.ndarray | list
3543
+ """
3356
3544
 
3357
3545
  if isinstance(new_y, list):
3358
3546
  new_y = np.array(new_y)
@@ -3371,7 +3559,8 @@ class vector:
3371
3559
  def z(self, new_z:np.ndarray | float | list):
3372
3560
  """ Set the z values of the vertices
3373
3561
 
3374
- /PARAM new_z: numpy array, float or list (but WolfArray is supported too)
3562
+ :param new_z: numpy array, float or list (but WolfArray is supported too)
3563
+ :type new_z: np.ndarray | float | list | WolfArray
3375
3564
  """
3376
3565
  from .wolf_array import WolfArray
3377
3566
 
@@ -3405,7 +3594,11 @@ class vector:
3405
3594
 
3406
3595
  @xyz.setter
3407
3596
  def xyz(self, new_xyz:np.ndarray | list):
3408
- """ Set the x, y, z values of the vertices """
3597
+ """ Set the x, y, z values of the vertices.
3598
+
3599
+ :param new_xyz: numpy array or list with x, y, z values - must have the same length as the number of vertices
3600
+ :type new_xyz: np.ndarray | list
3601
+ """
3409
3602
 
3410
3603
  if isinstance(new_xyz, list):
3411
3604
  new_xyz = np.array(new_xyz)
@@ -3431,7 +3624,11 @@ class vector:
3431
3624
 
3432
3625
  @xy.setter
3433
3626
  def xy(self, new_xy:np.ndarray | list):
3434
- """ Set the x, y values of the vertices """
3627
+ """ Set the x, y values of the vertices.
3628
+
3629
+ :param new_xy: numpy array or list with x, y values - must have the same length as the number of vertices
3630
+ :type new_xy: np.ndarray | list
3631
+ """
3435
3632
 
3436
3633
  if isinstance(new_xy, list):
3437
3634
  new_xy = np.array(new_xy)
@@ -3449,7 +3646,11 @@ class vector:
3449
3646
 
3450
3647
  @xz.setter
3451
3648
  def xz(self, new_xz:np.ndarray | list):
3452
- """ Set the x, z values of the vertices """
3649
+ """ Set the x, z values of the vertices.
3650
+
3651
+ :param new_xz: numpy array or list with x, z values - must have the same length as the number of vertices
3652
+ :type new_xz: np.ndarray | list
3653
+ """
3453
3654
 
3454
3655
  if isinstance(new_xz, list):
3455
3656
  new_xz = np.array(new_xz)
@@ -3472,7 +3673,11 @@ class vector:
3472
3673
 
3473
3674
  @xyzi.setter
3474
3675
  def xyzi(self, new_xyzi:np.ndarray | list):
3475
- """ Set the x, y, z, in_use values of the vertices """
3676
+ """ Set the x, y, z, in_use values of the vertices.
3677
+
3678
+ :param new_xyzi: numpy array or list with x, y, z, in_use values - must have the same length as the number of vertices
3679
+ :type new_xyzi: np.ndarray | list
3680
+ """
3476
3681
 
3477
3682
  if isinstance(new_xyzi, list):
3478
3683
  new_xyzi = np.array(new_xyzi)
@@ -3492,7 +3697,11 @@ class vector:
3492
3697
 
3493
3698
  @xyi.setter
3494
3699
  def xyi(self, new_xyi:np.ndarray | list):
3495
- """ Set the x, y, in_use values of the vertices """
3700
+ """ Set the x, y, in_use values of the vertices.
3701
+
3702
+ :param new_xyi: numpy array or list with x, y, in_use values - must have the same length as the number of vertices
3703
+ :type new_xyi: np.ndarray | list
3704
+ """
3496
3705
 
3497
3706
  if isinstance(new_xyi, list):
3498
3707
  new_xyi = np.array(new_xyi)
@@ -3511,7 +3720,11 @@ class vector:
3511
3720
 
3512
3721
  @i.setter
3513
3722
  def i(self, new_i:np.ndarray | list):
3514
- """ Set the in_use values of the vertices """
3723
+ """ Set the in_use values of the vertices.
3724
+
3725
+ :param new_i: numpy array or list with in_use values - must have the same length as the number of vertices
3726
+ :type new_i: np.ndarray | list
3727
+ """
3515
3728
 
3516
3729
  if isinstance(new_i, list):
3517
3730
  new_i = np.array(new_i)
@@ -3528,7 +3741,11 @@ class vector:
3528
3741
 
3529
3742
  @sz_curvi.setter
3530
3743
  def sz_curvi(self, sz_new:np.ndarray | list):
3531
- """ Interpolate the vertices based on the curvilinear abscissa """
3744
+ """ Interpolate the vertice Z-coordinates based on a polyline defined as curvilinear abscissa and Z-value.
3745
+
3746
+ :param sz_new: numpy array or list with curvilinear abscissa and Z-value pairs
3747
+ :type sz_new: np.ndarray | list
3748
+ """
3532
3749
 
3533
3750
  if isinstance(sz_new, list):
3534
3751
  sz_new = np.array(sz_new)
@@ -3542,6 +3759,30 @@ class vector:
3542
3759
  self._reset_listogl()
3543
3760
  self.reset_linestring()
3544
3761
 
3762
+ @s_curvi.setter
3763
+ def s_curvi(self, new_s:np.ndarray | list):
3764
+ """ Replace the vertice XY-coordinates based on the curvilinear abscissa.
3765
+
3766
+ :param new_s: numpy array or list with curvilinear abscissa values - must have the same length as the number of vertices
3767
+ :type new_s: np.ndarray | list
3768
+ """
3769
+
3770
+ if isinstance(new_s, list):
3771
+ new_s = np.array(new_s)
3772
+
3773
+ if len(new_s) != self.nbvertices:
3774
+ logging.warning(_('New s values have not the same length as the number of vertices'))
3775
+ return
3776
+
3777
+ poly = self.linestring
3778
+
3779
+ for idx, curvert in enumerate(self.myvertices):
3780
+ curvert.x, curvert.y = poly.interpolate(new_s[idx]).xy
3781
+
3782
+ self._reset_listogl()
3783
+ self.reset_linestring()
3784
+
3785
+
3545
3786
  def __str__(self):
3546
3787
  return self.myname
3547
3788
 
@@ -4251,7 +4492,7 @@ class zone:
4251
4492
  for curvect in self.myvectors:
4252
4493
  curvect.plot_legend(sx, sy, xmin, ymin, xmax, ymax, size)
4253
4494
 
4254
- def plot_matplotlib(self, ax:plt.Axes):
4495
+ def plot_matplotlib(self, ax:plt.Axes | tuple[Figure, Axes] = None, **kwargs):
4255
4496
  """
4256
4497
  Plot the zone using matplotlib
4257
4498
 
@@ -4259,9 +4500,18 @@ class zone:
4259
4500
  :param kwargs: additional arguments
4260
4501
  """
4261
4502
 
4503
+ if isinstance(ax, tuple):
4504
+ fig, ax = ax
4505
+ elif ax is None:
4506
+ fig, ax = plt.subplots()
4507
+ else:
4508
+ fig = ax.figure
4509
+
4262
4510
  for curvect in self.myvectors:
4263
4511
  curvect.plot_matplotlib(ax)
4264
4512
 
4513
+ return fig, ax
4514
+
4265
4515
  def select_vectors_from_point(self,x:float,y:float,inside=True):
4266
4516
  """
4267
4517
  Sélection du vecteur de la zone sur base d'une coordonnée (x,y) -- en 2D
@@ -6708,23 +6958,36 @@ class Zones(wx.Frame, Element_To_Draw):
6708
6958
 
6709
6959
  def import_dxf(self, fn, imported_elts=['POLYLINE','LWPOLYLINE','LINE']):
6710
6960
  """
6711
- Import d'un fichier DXF en tant qu'objets WOLF
6961
+ Import of a DXF file as a 'Zones'.
6962
+
6963
+ The DXF file is read and the elements are stored in zones based on their layers.
6964
+
6965
+ The supported elements are POLYLINE, LWPOLYLINE and LINE.
6966
+ If you want to import other elements, you must upgrade this routine `import_dxf`.
6967
+
6968
+ :param fn: name of the DXF file to import
6969
+ :param imported_elts: list of DXF elements to import. Default is ['POLYLINE','LWPOLYLINE','LINE'].
6970
+ :return: None
6712
6971
  """
6713
6972
  import ezdxf
6714
6973
 
6715
6974
  if not path.exists(fn):
6716
- try:
6717
- logging.warning(_('File not found !') + ' ' + fn)
6718
- except:
6719
- pass
6975
+ logging.warning(_('File not found !') + ' ' + fn)
6720
6976
  return
6721
6977
 
6978
+ for elt in imported_elts:
6979
+ assert elt in ['POLYLINE', 'LWPOLYLINE', 'LINE'], _('Unsupported DXF element: {}').format(elt)
6980
+
6981
+ self.is2D = False # we assume it's a 3D DXF
6982
+
6722
6983
  # Lecture du fichier dxf et identification du modelspace
6723
6984
  doc = ezdxf.readfile(fn)
6724
6985
  msp = doc.modelspace()
6725
- layers = doc.layers
6986
+ # layers = doc.layers
6726
6987
 
6727
6988
  used_layers = {}
6989
+ notloaded = {}
6990
+
6728
6991
  # Bouclage sur les éléments du DXF pour identifier les layers utiles et ensuite créer les zones adhoc
6729
6992
  for e in msp:
6730
6993
  if doc.layers.get(e.dxf.layer).is_on():
@@ -6750,14 +7013,23 @@ class Zones(wx.Frame, Element_To_Draw):
6750
7013
  curlayer = used_layers[e.dxf.layer]
6751
7014
  curlayer[e.dxftype().lower()]=0
6752
7015
  else:
6753
- logging.warning(_('DXF element not supported : ') + e.dxftype())
7016
+ if not e.dxftype() in notloaded.keys():
7017
+ notloaded[e.dxftype()] = 0
7018
+
7019
+ notloaded[e.dxftype()] += 1
7020
+ logging.debug(_('DXF element not supported : ') + e.dxftype())
6754
7021
  else:
6755
7022
  logging.info(_('Layer {} is off'.format(e.dxf.layer)))
6756
7023
 
7024
+ if len(notloaded)>0:
7025
+ logging.warning(_('Not loaded DXF elements : '))
7026
+ for curtype in notloaded.keys():
7027
+ logging.warning(_(' {} : {}'.format(curtype, notloaded[curtype])))
7028
+
6757
7029
  # Création des zones
6758
7030
  for curlayer in used_layers.keys():
6759
7031
  for curtype in used_layers[curlayer].keys():
6760
- curzone = used_layers[curlayer][curtype] = zone(name = '{} - {}'.format(curlayer,curtype),is2D=self.is2D,parent=self)
7032
+ curzone = used_layers[curlayer][curtype] = zone(name = '{} - {}'.format(curlayer,curtype), is2D=self.is2D, parent=self)
6761
7033
  self.add_zone(curzone)
6762
7034
 
6763
7035
  # Nouveau bouclage sur les éléments du DXF pour remplissage
@@ -6974,12 +7246,21 @@ class Zones(wx.Frame, Element_To_Draw):
6974
7246
  for curzone in self.myzones:
6975
7247
  curzone.plot(sx=sx, sy=sy, xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax, size=size)
6976
7248
 
6977
- def plot_matplotlib(self, ax:plt.Axes):
7249
+ def plot_matplotlib(self, ax:Axes | tuple[Figure, Axes] = None):
6978
7250
  """ Plot with matplotlib """
6979
7251
 
7252
+ if isinstance(ax, tuple):
7253
+ fig, ax = ax
7254
+ elif ax is None:
7255
+ fig, ax = plt.subplots()
7256
+ else:
7257
+ fig = ax.figure
7258
+
6980
7259
  for curzone in self.myzones:
6981
7260
  curzone.plot_matplotlib(ax)
6982
7261
 
7262
+ return fig, ax
7263
+
6983
7264
  def select_vectors_from_point(self, x:float, y:float, inside=True):
6984
7265
  """
6985
7266
  Sélection de vecteurs dans chaque zones sur base d'une coordonnée