wolfhece 2.2.38__py3-none-any.whl → 2.2.40__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.
Files changed (50) hide show
  1. wolfhece/Coordinates_operations.py +5 -0
  2. wolfhece/GraphNotebook.py +72 -1
  3. wolfhece/GraphProfile.py +1 -1
  4. wolfhece/MulticriteriAnalysis.py +1579 -0
  5. wolfhece/PandasGrid.py +62 -1
  6. wolfhece/PyCrosssections.py +194 -43
  7. wolfhece/PyDraw.py +891 -73
  8. wolfhece/PyGui.py +913 -72
  9. wolfhece/PyGuiHydrology.py +528 -74
  10. wolfhece/PyPalette.py +26 -4
  11. wolfhece/PyParams.py +33 -0
  12. wolfhece/PyPictures.py +2 -2
  13. wolfhece/PyVertex.py +25 -0
  14. wolfhece/PyVertexvectors.py +94 -28
  15. wolfhece/PyWMS.py +52 -36
  16. wolfhece/acceptability/acceptability.py +15 -8
  17. wolfhece/acceptability/acceptability_gui.py +507 -360
  18. wolfhece/acceptability/func.py +80 -183
  19. wolfhece/apps/version.py +1 -1
  20. wolfhece/compare_series.py +480 -0
  21. wolfhece/drawing_obj.py +12 -1
  22. wolfhece/hydrology/Catchment.py +228 -162
  23. wolfhece/hydrology/Internal_variables.py +43 -2
  24. wolfhece/hydrology/Models_characteristics.py +69 -67
  25. wolfhece/hydrology/Optimisation.py +893 -182
  26. wolfhece/hydrology/PyWatershed.py +267 -165
  27. wolfhece/hydrology/SubBasin.py +185 -140
  28. wolfhece/hydrology/cst_exchanges.py +76 -1
  29. wolfhece/hydrology/forcedexchanges.py +413 -49
  30. wolfhece/hydrology/read.py +65 -5
  31. wolfhece/hydrometry/kiwis.py +14 -7
  32. wolfhece/insyde_be/INBE_func.py +746 -0
  33. wolfhece/insyde_be/INBE_gui.py +1776 -0
  34. wolfhece/insyde_be/__init__.py +3 -0
  35. wolfhece/interpolating_raster.py +366 -0
  36. wolfhece/irm_alaro.py +1457 -0
  37. wolfhece/irm_qdf.py +889 -57
  38. wolfhece/lazviewer/laz_viewer.py +4 -1
  39. wolfhece/lifewatch.py +6 -3
  40. wolfhece/picc.py +124 -8
  41. wolfhece/pyLandUseFlanders.py +146 -0
  42. wolfhece/pydownloader.py +35 -1
  43. wolfhece/pywalous.py +225 -31
  44. wolfhece/toolshydrology_dll.py +149 -0
  45. wolfhece/wolf_array.py +63 -25
  46. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/METADATA +3 -1
  47. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/RECORD +50 -41
  48. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/WHEEL +0 -0
  49. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/entry_points.txt +0 -0
  50. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/top_level.txt +0 -0
wolfhece/PandasGrid.py CHANGED
@@ -4,8 +4,69 @@ import pandas as pd
4
4
  import numpy as np
5
5
  import matplotlib.pyplot as plt
6
6
 
7
+ class DictGrid(wx.Dialog):
8
+
9
+ def __init__(self, parent, id, data: dict[dict]):
10
+
11
+ super().__init__(parent, title=f"Edit: {id}", size=(600, 400))
12
+
13
+ self.data = data
14
+
15
+ vbox = wx.BoxSizer(wx.VERTICAL)
16
+
17
+ # Create the grid
18
+ self.grid = wx.grid.Grid(self)
19
+
20
+ first_elem = next(iter(data.values()))
21
+ self.grid.CreateGrid(len(data)+1, len(list(first_elem.keys()))+1)
22
+
23
+ # Set column labels
24
+ for col, colname in enumerate(first_elem.keys()):
25
+ self.grid.SetColLabelValue(col+1, str(colname))
26
+
27
+ # Fill grid and make cells read-only
28
+ for row, vals in data.items():
29
+ for col, colname in enumerate(first_elem.keys()):
30
+ val = str(vals[colname])
31
+ self.grid.SetCellValue(row+1, col+1, val)
32
+ # self.grid.SetReadOnly(row, col, True)
33
+
34
+ vbox.Add(self.grid, 1, wx.EXPAND | wx.ALL, 10)
35
+
36
+ # Add a button to show histogram
37
+ sizer_buttons = wx.BoxSizer(wx.HORIZONTAL)
38
+ self._ok_button = wx.Button(self, label="OK")
39
+ self._cancel_button = wx.Button(self, label="Cancel")
40
+ sizer_buttons.Add(self._ok_button, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
41
+ sizer_buttons.Add(self._cancel_button, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
42
+
43
+ self._ok_button.Bind(wx.EVT_BUTTON, self.OnOk)
44
+ self._cancel_button.Bind(wx.EVT_BUTTON, self.Close)
45
+
46
+ vbox.Add(sizer_buttons, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
47
+ self.SetSizer(vbox)
48
+
49
+ def get_dict(self):
50
+ """ Return the data as a dictionary. """
51
+ new_data = {}
52
+ for row in range(1, self.grid.GetNumberRows()):
53
+ new_data[row] = {}
54
+ for col in range(1, self.grid.GetNumberCols()):
55
+ colname = self.grid.GetColLabelValue(col)
56
+ new_data[row][colname] = self.grid.GetCellValue(row, col)
57
+ return new_data
58
+
59
+ def OnOk(self, event):
60
+ """ Handle the OK button click. """
61
+ # Here you can implement logic to save changes if needed
62
+ # For now, we just close the dialog
63
+ self.Hide()
64
+
65
+ def Close(self, event=None):
66
+ """ Close the dialog. """
67
+ self.Destroy()
7
68
  class PandasGrid(wx.Dialog):
8
-
69
+
9
70
  def __init__(self, parent, id, df: pd.DataFrame):
10
71
  super().__init__(parent, title=f"DataFrame characteristics: {id}", size=(600, 400))
11
72
 
@@ -155,6 +155,10 @@ class profile(vector):
155
155
  # - bankleft_vertex, bankright_vertex, bed_vertex qui retournent un vertex quel que soit le format de stockage
156
156
  # - bankleft_s3D, bankright_s3D, bed_s3D qui retournent la position curvi 3D quel que soit le format de stockage
157
157
  # - bankleft_sz, bankright_sz, bed_sz qui retournent un couple (s,z) quel que soit le format de stockage
158
+
159
+
160
+
161
+
158
162
  self._bankleft=None
159
163
  self._bankright=None
160
164
  self._bed=None
@@ -392,6 +396,20 @@ class profile(vector):
392
396
  s = ls2d.project(Point(curvert.x, curvert.y))
393
397
  return s, curvert.z
394
398
 
399
+ @property
400
+ def bankleft_down_sz(self):
401
+ ls2d = self.asshapely_ls()
402
+ curvert = self.bankleft_down_vertex
403
+ s = ls2d.project(Point(curvert.x, curvert.y))
404
+ return s, curvert.z
405
+
406
+ @property
407
+ def bankright_down_sz(self):
408
+ ls2d = self.asshapely_ls()
409
+ curvert = self.bankright_down_vertex
410
+ s = ls2d.project(Point(curvert.x, curvert.y))
411
+ return s, curvert.z
412
+
395
413
  def verif(self):
396
414
 
397
415
  self.update_lengths()
@@ -842,7 +860,7 @@ class profile(vector):
842
860
  curvert = wolfvertex(xy[i,0],xy[i,1],sz[i,1])
843
861
  self.add_vertex(curvert)
844
862
 
845
- def get_sz_banksbed(self, cumul=True, force:bool=False) -> tuple[float, float, float, float, float, float]:
863
+ def get_sz_banksbed(self, cumul=True, force:bool=False) -> tuple[float, float, float, float, float, float, float, float, float, float]:
846
864
  """
847
865
  Retourne les positions des points de référence mais avec la coordonnée curvi 2D
848
866
  - (sleft, sbed, sright, zleft, zbed, zright)
@@ -893,16 +911,46 @@ class profile(vector):
893
911
  sbed=-99999.
894
912
  zbed=-99999.
895
913
 
914
+ if self.bankleft_down is not None:
915
+ if cumul:
916
+ sbankleft_down, zbankleft_down = self.bankleft_down_sz
917
+ else:
918
+ curvert = self.bankleft_down_vertex
919
+ x2 = curvert.x
920
+ y2 = curvert.y
921
+ sbankleft_down = math.sqrt((x2-x1)**2.+(y2-y1)**2.)
922
+ zbankleft_down=curvert.z
923
+ else:
924
+ sbankleft_down=-99999.
925
+ zbankleft_down=-99999.
926
+
927
+ if self.bankright_down is not None:
928
+ if cumul:
929
+ sbankright_down, zbankright_down = self.bankright_down_sz
930
+ else:
931
+ curvert = self.bankright_down_vertex
932
+ x2 = curvert.x
933
+ y2 = curvert.y
934
+ sbankright_down = math.sqrt((x2-x1)**2.+(y2-y1)**2.)
935
+ zbankright_down=curvert.z
936
+ else:
937
+ sbankright_down=-99999.
938
+ zbankright_down=-99999.
939
+
896
940
  if self.add_sdatum:
897
941
  sleft+=self.sdatum
898
942
  sbed+=self.sdatum
899
943
  sright+=self.sdatum
944
+ sbankleft_down+=self.sdatum
945
+ sbankright_down+=self.sdatum
900
946
  if self.add_zdatum:
901
947
  zleft+=self.zdatum
902
948
  zbed+=self.zdatum
903
949
  zright+=self.zdatum
950
+ zbankleft_down+=self.zdatum
951
+ zbankright_down+=self.zdatum
904
952
 
905
- return sleft,sbed,sright,zleft,zbed,zright
953
+ return sleft,sbed,sright,zleft,zbed,zright, sbankleft_down, sbankright_down, zbankleft_down, zbankright_down
906
954
 
907
955
  def get_s3d_banksbed(self, force:bool=False)-> tuple[float, float, float]:
908
956
  """
@@ -1010,7 +1058,7 @@ class profile(vector):
1010
1058
  # plot
1011
1059
  x,y=self.get_sz()
1012
1060
 
1013
- sl,sb,sr,yl,yb,yr = self.get_sz_banksbed()
1061
+ sl,sb,sr,yl,yb,yr, sld, srd, yld, yrd = self.get_sz_banksbed()
1014
1062
 
1015
1063
  if centerx >0. and sb!=-99999.:
1016
1064
  decal = centerx-sb
@@ -1041,12 +1089,16 @@ class profile(vector):
1041
1089
  ax.plot(sb,yb,'ob',alpha=alpha)
1042
1090
  if sr != -99999.:
1043
1091
  ax.plot(sr,yr,'og',alpha=alpha)
1092
+ if sld != -99999.:
1093
+ ax.plot(sld,yld,'*r',alpha=alpha)
1094
+ if srd != -99999.:
1095
+ ax.plot(srd,yrd,'*g',alpha=alpha)
1044
1096
 
1045
1097
  def plot_cs(self, fwl=None, show=False, forceaspect=True, fig:Figure=None, ax:Axes=None, plotlaz=True, clear=True, linked_arrays:dict={}):
1046
1098
  # plot
1047
1099
  x,y=self.get_sz()
1048
1100
 
1049
- sl,sb,sr,yl,yb,yr = self.get_sz_banksbed()
1101
+ sl,sb,sr,yl,yb,yr, sld, srd, yld, yrd = self.get_sz_banksbed()
1050
1102
 
1051
1103
  xmin=x[0]
1052
1104
  xmax=x[-1]
@@ -1094,6 +1146,10 @@ class profile(vector):
1094
1146
  ax.plot(sb,yb,'ob')
1095
1147
  if sr != -99999.:
1096
1148
  ax.plot(sr,yr,'og')
1149
+ if sld != -99999.:
1150
+ ax.plot(sld,yld,'*r')
1151
+ if srd != -99999.:
1152
+ ax.plot(srd,yrd,'*g')
1097
1153
 
1098
1154
  ax.set_title(self.myname)
1099
1155
  ax.set_xlabel(_('Distance [m]'))
@@ -1392,7 +1448,7 @@ class profile(vector):
1392
1448
  idsimul = [cursimul[0] for cursimul in simuls]
1393
1449
  zsimul = [cursimul[3] for cursimul in simuls]
1394
1450
 
1395
- sl,sb,sr,zl,zb,zr = self.get_sz_banksbed()
1451
+ sl,sb,sr,zl,zb,zr, sld, srd, zld, zrd = self.get_sz_banksbed()
1396
1452
  x,y = self.get_sz()
1397
1453
 
1398
1454
  if fwl is None:
@@ -1538,6 +1594,10 @@ class profile(vector):
1538
1594
  myax1.plot(sb,zb,_('ob'), label= _('River bed'))
1539
1595
  if sr != -99999.:
1540
1596
  myax1.plot(sr,zr,_('og'), label= _('Right bank'))
1597
+ if sld != -99999.:
1598
+ myax1.plot(sld,zld,_('*r'), label= _('Left bank down'))
1599
+ if srd != -99999.:
1600
+ myax1.plot(srd,zrd,_('*g'), label= _('Right bank down'))
1541
1601
 
1542
1602
  #Available simulations
1543
1603
  if zsimul is not None:
@@ -1614,7 +1674,7 @@ class profile(vector):
1614
1674
  idsimul= [cursimul[0] for cursimul in simuls]
1615
1675
 
1616
1676
 
1617
- sl,sb,sr,zl,zb,zr = self.get_sz_banksbed()
1677
+ sl,sb,sr,zl,zb,zr, sld, srd, zld, zrd = self.get_sz_banksbed()
1618
1678
  x,y = self.get_sz()
1619
1679
 
1620
1680
  if fwl is None:
@@ -1710,7 +1770,7 @@ class profile(vector):
1710
1770
  - fwq: for water discharge.
1711
1771
 
1712
1772
  """
1713
- sl,sb,sr,zl,zb,zr = self.get_sz_banksbed()
1773
+ sl,sb,sr,zl,zb,zr, sld, srd, zld, zrd = self.get_sz_banksbed()
1714
1774
  x,y = self.get_sz()
1715
1775
 
1716
1776
  if fwl is None:
@@ -1894,7 +1954,7 @@ class crosssections(Element_To_Draw):
1894
1954
  self.sorted = {}
1895
1955
  self.plotted = False
1896
1956
 
1897
- if isinstance(lines, pd.DataFrame):
1957
+ if isinstance(lines, pd.DataFrame): # Format is '2025_xlsx'
1898
1958
 
1899
1959
  self.format='2025_xlsx'
1900
1960
 
@@ -1919,6 +1979,13 @@ class crosssections(Element_To_Draw):
1919
1979
  curdict = self.myprofiles[name] = {}
1920
1980
  curdict['index'] = index
1921
1981
  curdict['cs'] = profile(name=name, parent=self)
1982
+
1983
+ curdict['left'] = None
1984
+ curdict['bed'] = None
1985
+ curdict['right'] = None
1986
+ curdict['left_down'] = None
1987
+ curdict['right_down'] = None
1988
+
1922
1989
  cursect:profile
1923
1990
  cursect = curdict['cs']
1924
1991
 
@@ -1968,6 +2035,7 @@ class crosssections(Element_To_Draw):
1968
2035
  logging.debug(name)
1969
2036
 
1970
2037
  elif len(lines)>0:
2038
+
1971
2039
  if format=='2000':
1972
2040
  self.format='2000'
1973
2041
  lines.pop(0)
@@ -1987,6 +2055,12 @@ class crosssections(Element_To_Draw):
1987
2055
  cursect:profile
1988
2056
  cursect=curdict['cs']
1989
2057
 
2058
+ curdict['left'] = None
2059
+ curdict['bed'] = None
2060
+ curdict['right'] = None
2061
+ curdict['left_down'] = None
2062
+ curdict['right_down'] = None
2063
+
1990
2064
  x=float(vals[1])
1991
2065
  y=float(vals[2])
1992
2066
  type=vals[3]
@@ -2044,6 +2118,11 @@ class crosssections(Element_To_Draw):
2044
2118
  curdict['cs']=profile(name=name,parent=self)
2045
2119
  cursect:profile
2046
2120
  cursect=curdict['cs']
2121
+ curdict['left'] = None
2122
+ curdict['bed'] = None
2123
+ curdict['right'] = None
2124
+ curdict['left_down'] = None
2125
+ curdict['right_down'] = None
2047
2126
 
2048
2127
  x=float(vals[xpos].replace(',','.'))
2049
2128
  y=float(vals[ypos].replace(',','.'))
@@ -2131,6 +2210,11 @@ class crosssections(Element_To_Draw):
2131
2210
  curdict['cs']=profile(name=name,parent=self)
2132
2211
  cursect:profile
2133
2212
  cursect=curdict['cs']
2213
+ curdict['left'] = None
2214
+ curdict['bed'] = None
2215
+ curdict['right'] = None
2216
+ curdict['left_down'] = None
2217
+ curdict['right_down'] = None
2134
2218
 
2135
2219
  cursect.zdatum = zdatum
2136
2220
  cursect.add_zdatum = add_zdatum
@@ -2543,9 +2627,10 @@ class crosssections(Element_To_Draw):
2543
2627
 
2544
2628
  for curprof in self.myprofiles.keys():
2545
2629
  curdict=self.myprofiles[curprof]
2546
- curprof=curdict['cs']
2547
- self.myzone.add_vector(curprof)
2548
- curprof.parentzone=self.myzone
2630
+ curvec=curdict['cs']
2631
+ curvec:vector
2632
+ if curvec.used:
2633
+ self.myzone.add_vector(curvec, forceparent=True)
2549
2634
 
2550
2635
  if self.plotted:
2551
2636
  self._prep_listogl() #FIXME : Does not work in the context of a 1D model
@@ -2613,13 +2698,15 @@ class crosssections(Element_To_Draw):
2613
2698
 
2614
2699
  self.set_zones(True)
2615
2700
 
2616
- def saveas(self,filename=None):
2701
+ def saveas(self,filename:str | Path = None):
2617
2702
  """ Save the cross-sections to a file in the specified format. """
2618
2703
 
2619
2704
  self.forcesuper=False
2620
2705
 
2621
2706
  if filename is not None:
2622
- self.filename = filename
2707
+ self.filename = str(filename)
2708
+
2709
+ assert isinstance(self.filename, str), _('Filename must be a string.')
2623
2710
 
2624
2711
  if self.filename is None:
2625
2712
  logging.error(_('No Filename -- Retry !'))
@@ -2633,22 +2720,22 @@ class crosssections(Element_To_Draw):
2633
2720
 
2634
2721
  with open(self.filename,'w') as f:
2635
2722
  f.write("Profile\tx\ty\tBerge\tz\n")
2636
- for idx,curvect in self.myprofiles.items():
2637
- curprof=curvect['cs']
2723
+ for idx,locdict in self.myprofiles.items():
2724
+ curprof=locdict['cs']
2638
2725
  curprof.save(f)
2639
2726
 
2640
2727
  elif self.format=='2025_xlsx':
2641
2728
  # For the 2025_xlsx format, we need to save the data using pandas
2642
2729
  data = []
2643
- for idx, curvect in self.myprofiles.items():
2644
- curprof = curvect['cs']
2730
+ for idx, locdict in self.myprofiles.items():
2731
+ curprof = locdict['cs']
2645
2732
  for vertex in curprof.myvertices:
2646
2733
  data.append({
2647
2734
  'Num': idx,
2648
2735
  'X': vertex.x,
2649
2736
  'Y': vertex.y,
2650
- 'Z': vertex.z,
2651
- 'Code': curprof.get_label(vertex)
2737
+ 'Z': vertex.z * 1000., # Convert to mm
2738
+ 'Code': self.get_label(locdict, vertex)
2652
2739
  })
2653
2740
 
2654
2741
  df = pd.DataFrame(data)
@@ -2690,6 +2777,43 @@ class crosssections(Element_To_Draw):
2690
2777
  rbs=cursect.get_s_from_xy(cursect.bankright),
2691
2778
  rbz=cursect.bankright.z))
2692
2779
 
2780
+ def get_label(self, profile_dict:dict, vertex:wolfvertex):
2781
+ """ Get the label for a vertex based on its type.
2782
+
2783
+ :param profile_dict: Dictionary containing the profile information.
2784
+ :type profile_dict: dict
2785
+ :param vertex: The vertex for which to get the label.
2786
+ :type vertex: wolfvertex
2787
+ :return: The label for the vertex.
2788
+ :rtype: str
2789
+ """
2790
+ try:
2791
+ if profile_dict['left'] is not None:
2792
+ if vertex.is_like(profile_dict['left']):
2793
+ return 'HBG'
2794
+
2795
+ if profile_dict['bed'] is not None:
2796
+ if vertex.is_like(profile_dict['bed']):
2797
+ return 'THA'
2798
+
2799
+ if profile_dict['right'] is not None:
2800
+ if vertex.is_like(profile_dict['right']):
2801
+ return 'HBD'
2802
+
2803
+ if profile_dict['left_down'] is not None:
2804
+ if vertex.is_like(profile_dict['left_down']):
2805
+ return 'BBG'
2806
+
2807
+ if profile_dict['right_down'] is not None:
2808
+ if vertex.is_like(profile_dict['right_down']):
2809
+ return 'BBD'
2810
+
2811
+ return ''
2812
+ except:
2813
+ logging.error(_('Error in get_label for vertex: {v}').format(v=vertex))
2814
+ logging.info(_('Please report this bug to Pierre Archambeau.'))
2815
+ return ''
2816
+
2693
2817
  def verif_bed(self):
2694
2818
  """Verification de l'existence du point lit mineur sinon attribution de l'altitude minimale"""
2695
2819
 
@@ -3237,7 +3361,7 @@ class Interpolator():
3237
3361
 
3238
3362
  return nbpts,points
3239
3363
 
3240
- def export_gltf(self,points=None,triangles=None):
3364
+ def export_gltf(self, points=None, triangles=None, fn:str | Path = None):
3241
3365
 
3242
3366
  if points is None and triangles is None:
3243
3367
  points,triangles= self.get_triangles()
@@ -3297,14 +3421,22 @@ class Interpolator():
3297
3421
  )
3298
3422
  gltf.set_binary_blob(triangles_binary_blob + points_binary_blob)
3299
3423
 
3300
- dlg=wx.FileDialog(None,_('Choose filename'),wildcard='binary gltf2 (*.glb)|*.glb|gltf2 (*.gltf)|*.gltf|All (*.*)|*.*',style=wx.FD_SAVE)
3301
- ret=dlg.ShowModal()
3302
- if ret==wx.ID_CANCEL:
3303
- dlg.Destroy()
3304
- return
3305
-
3306
- fn=dlg.GetPath()
3307
- dlg.Destroy()
3424
+ if fn is not None:
3425
+ if isinstance(fn, str):
3426
+ fn = Path(fn)
3427
+ else:
3428
+ try:
3429
+ dlg=wx.FileDialog(None,_('Choose filename'),wildcard='binary gltf2 (*.glb)|*.glb|gltf2 (*.gltf)|*.gltf|All (*.*)|*.*',style=wx.FD_SAVE)
3430
+ ret=dlg.ShowModal()
3431
+ if ret==wx.ID_CANCEL:
3432
+ dlg.Destroy()
3433
+ return
3434
+
3435
+ fn=dlg.GetPath()
3436
+ dlg.Destroy()
3437
+ except:
3438
+ logging.error(_('Wx FileDialog error. Is wx running ?'))
3439
+ return
3308
3440
 
3309
3441
  gltf.save(fn)
3310
3442
 
@@ -3334,6 +3466,9 @@ class Interpolators():
3334
3466
  :param cs: objet 'crosssections' contenant les sections en travers --> voir PyCrosssections
3335
3467
  """
3336
3468
 
3469
+ self.points = None
3470
+ self.triangles = None
3471
+
3337
3472
  self.mybanks = [curv for curzone in banks.myzones for curv in curzone.myvectors]
3338
3473
 
3339
3474
  cs.set_zones()
@@ -3364,7 +3499,7 @@ class Interpolators():
3364
3499
 
3365
3500
  cs1=cs2
3366
3501
  else:
3367
- # Les sections n'ont pas été triées --> on les traite dans l'ordre
3502
+ # Les sections n'ont pas été triées --> on les traite dans l'ordre d'énumération
3368
3503
  for i in range(zonecs.nbvectors-1):
3369
3504
  cs1=zonecs.myvectors[i]
3370
3505
  cs2=zonecs.myvectors[i+1]
@@ -3403,7 +3538,17 @@ class Interpolators():
3403
3538
  triangles.append(tr+decal)
3404
3539
  decal+=nbpts
3405
3540
 
3406
- curinterp.export_gltf(np.concatenate(points),np.concatenate(triangles))
3541
+
3542
+ self.points, self.triangles = np.concatenate(points), np.concatenate(triangles)
3543
+
3544
+ def export_gltf(self, fn:str | Path = None):
3545
+ """ Export the interpolated sections as a glTF file. """
3546
+ if self.points is None or self.triangles is None:
3547
+ logging.error('No points or triangles available for export.')
3548
+ return
3549
+
3550
+ interp = Interpolator()
3551
+ interp.export_gltf(points=self.points, triangles=self.triangles, fn=fn)
3407
3552
 
3408
3553
 
3409
3554
  def viewer_interpolator(self):
@@ -3416,16 +3561,22 @@ class Interpolators():
3416
3561
 
3417
3562
  myviewer(xyz,0)
3418
3563
 
3419
- def interp_on_array(self, myarray, method:Literal["nearest", "linear", "cubic"]):
3420
-
3421
- xy=[]
3422
- z=[]
3423
- for curinterp in self.myinterp:
3424
- tmpxy,tmpz = curinterp.get_xy_z_for_griddata()
3425
- xy.append(tmpxy)
3426
- z.append(tmpz)
3427
-
3428
- xy = np.concatenate(xy)
3429
- z = np.concatenate(z)
3430
-
3431
- myarray.interpolate_on_cloud(xy,z,method)
3564
+ def interp_on_array(self, myarray,
3565
+ method:Literal["nearest", "linear", "cubic"],
3566
+ use_cloud:bool = True):
3567
+
3568
+ if use_cloud:
3569
+ xy=[]
3570
+ z=[]
3571
+ for curinterp in self.myinterp:
3572
+ tmpxy,tmpz = curinterp.get_xy_z_for_griddata()
3573
+ xy.append(tmpxy)
3574
+ z.append(tmpz)
3575
+
3576
+ xy = np.concatenate(xy)
3577
+ z = np.concatenate(z)
3578
+ myarray.interpolate_on_cloud(xy,z,method)
3579
+ else:
3580
+ for interp in self.myinterp:
3581
+ n, pts, tri = interp.get_triangles(forgltf=False)
3582
+ myarray.interpolate_on_triangulation(pts, tri, interp_method= 'scipy')