wolfhece 2.2.45__py3-none-any.whl → 2.2.47__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.
@@ -2170,7 +2170,7 @@ class profile(vector):
2170
2170
  ds = min(curarray.dx,curarray.dy)
2171
2171
  nb = int(np.ceil(length/ds*2))
2172
2172
 
2173
- alls = np.linspace(0,int(length),nb)
2173
+ alls = np.linspace(0, length, nb, endpoint=True)
2174
2174
 
2175
2175
  pts = [self.linestring.interpolate(curs) for curs in alls]
2176
2176
 
@@ -2227,6 +2227,25 @@ class profile(vector):
2227
2227
  if srd != -99999.:
2228
2228
  ax.plot(srd,yrd,'*g',alpha=alpha)
2229
2229
 
2230
+ def _plot_only_cs_min_at_x0(self,
2231
+ fig:Figure=None, ax:Axes=None,
2232
+ label='', alpha=0.8, lw=1., style: str ='dashed',
2233
+ grid=True, col_ax: str = 'black'):
2234
+
2235
+ """ Plot only the cross section line on an existing axis.
2236
+ We assume that the minimum elevation is at x=0.
2237
+ """
2238
+
2239
+ x,y=self.get_sz()
2240
+ x = x - x[np.argmin(y)]
2241
+
2242
+ ax.plot(x,y,color=col_ax,
2243
+ lw=lw,
2244
+ linestyle=style,
2245
+ alpha=alpha,
2246
+ label=label)
2247
+
2248
+
2230
2249
  def plot_cs(self,
2231
2250
  fwl:float = None, show:bool = False, forceaspect:bool = True,
2232
2251
  fig:Figure = None, ax:Axes = None,
@@ -2329,6 +2348,32 @@ class profile(vector):
2329
2348
 
2330
2349
  return sl,sb,sr,yl,yb,yr
2331
2350
 
2351
+ def _plot_extremities(self, ax:plt.Axes, s:int = 50, colors:tuple[str, str] = ('blue', 'green')) -> None:
2352
+ """
2353
+ Plot the extremities of the cross-section on the given axes.
2354
+ """
2355
+ x_left = self[0].x
2356
+ y_left = self[0].y
2357
+ x_right = self[-1].x
2358
+ y_right = self[-1].y
2359
+
2360
+ ax.scatter(x_left, y_left, color=colors[0], s=s, label='Left extremity')
2361
+ ax.scatter(x_right, y_right, color=colors[1], s=s, label='Right extremity')
2362
+ ax.legend()
2363
+
2364
+ def _plot_extremities_sz(self, ax:plt.Axes, s:int = 10, colors:tuple[str, str] = ('blue', 'green')) -> None:
2365
+ """
2366
+ Plot the extremities of the cross-section on the given axes.
2367
+ """
2368
+ x_left = 0. #self[0].x
2369
+ y_left = self[0].z
2370
+ x_right = self.length2D #self[-1].x
2371
+ y_right = self[-1].z
2372
+
2373
+ ax.scatter(x_left, y_left, color=colors[0], s=s)
2374
+ ax.scatter(x_right, y_right, color=colors[1], s=s)
2375
+ ax.legend()
2376
+
2332
2377
 
2333
2378
  class crosssections(Element_To_Draw):
2334
2379
  """
@@ -2350,7 +2395,7 @@ class crosssections(Element_To_Draw):
2350
2395
  ['right_down']: wolfvertex
2351
2396
  ['cs'] : profile (surcharge de vector)
2352
2397
 
2353
- Pour le moment, il est possible de lire les fichiers et d'effectuer cerrains traitements (tri selon vecteur, export gltf...).
2398
+ Pour le moment, il est possible de lire les fichiers et d'effectuer certains traitements (tri selon vecteur, export gltf...).
2354
2399
 
2355
2400
  Une instance de cet objet peut être ajouté à une instance graphique WOLF pour affichage.
2356
2401
  Pour ce faire:
@@ -2363,7 +2408,7 @@ class crosssections(Element_To_Draw):
2363
2408
 
2364
2409
  """
2365
2410
 
2366
- myprofiles:dict['cs':profile, 'index':int, 'left':wolfvertex, 'bed':wolfvertex, 'right':wolfvertex, 'left_down':wolfvertex, 'right_down':wolfvertex]
2411
+ myprofiles:dict[str | int: dict['cs':profile, 'index':int, 'left':wolfvertex, 'bed':wolfvertex, 'right':wolfvertex, 'left_down':wolfvertex, 'right_down':wolfvertex]]
2367
2412
  mygenprofiles:dict
2368
2413
 
2369
2414
  def __init__(self,
@@ -2395,6 +2440,9 @@ class crosssections(Element_To_Draw):
2395
2440
 
2396
2441
  """
2397
2442
 
2443
+ self.dirlaz = None
2444
+ self.gridlaz = None
2445
+
2398
2446
  assert format in ['2000','2022','2025_xlsx','vecz','sxy', 'zones'], _('Format %s not supported!')%format
2399
2447
 
2400
2448
  super().__init__(idx=idx, plotted= plotted, mapviewer=mapviewer, need_for_wx=False)
@@ -2414,7 +2462,7 @@ class crosssections(Element_To_Draw):
2414
2462
  self.myzones=None
2415
2463
  self.myzone=None
2416
2464
 
2417
- if isinstance(dirlaz,str):
2465
+ if isinstance(dirlaz, (str, Path)):
2418
2466
  if path.exists(dirlaz):
2419
2467
  self.dirlaz=dirlaz
2420
2468
  self.gridlaz = xyz_laz_grids(self.dirlaz)
@@ -2462,7 +2510,15 @@ class crosssections(Element_To_Draw):
2462
2510
  self.cloud_all = None
2463
2511
 
2464
2512
  self.multils = None
2513
+
2514
+ self.sorted:dict[str, dict['sorted': list[vector], 'support':LineString]]
2515
+ # Dictionnaire des sections triées, peut contenir plusieurs tris selon différents vecteurs de tri.
2516
+ # Ceci est utile pour créer des sous-groupes de sections le long d'un cours d'eau ou de cours d'eau différents.
2517
+ # Chaque entrée est un dictionnaire avec les clés:
2518
+ # - 'sorted' : liste des sections triées
2519
+ # - 'support': LineString support du tri
2465
2520
  self.sorted = {}
2521
+
2466
2522
  self.plotted = False
2467
2523
 
2468
2524
  if isinstance(lines, pd.DataFrame): # Format is '2025_xlsx'
@@ -2808,11 +2864,7 @@ class crosssections(Element_To_Draw):
2808
2864
  curdict['right_down'] = None
2809
2865
 
2810
2866
  index+=1
2811
- curdict['cs']=profile(name=curvec.myname, parent=self)
2812
- cursect:profile
2813
- cursect=curdict['cs']
2814
-
2815
- cursect.myvertices = curvec.myvertices.copy()
2867
+ curdict['cs']=profile(name=curvec.myname, parent=self, data_sect=curvec.myvertices.copy())
2816
2868
 
2817
2869
  self.verif_bed()
2818
2870
  self.find_minmax(True)
@@ -2916,16 +2968,38 @@ class crosssections(Element_To_Draw):
2916
2968
  keys = [curprof.myname for curprof in curlist]
2917
2969
  if which_prof in keys:
2918
2970
  return curlist[keys.index(which_prof)]
2971
+ else:
2972
+ logging.error(_('Profile %s not found in sorted dictionaries!')%which_prof)
2973
+ return None
2974
+
2919
2975
  elif isinstance(which_prof, int):
2976
+ if which_prof<0 or which_prof>=len(curlist):
2977
+ logging.error(_('Index %d out of range (0 to %d)!')%(which_prof,len(curlist)-1))
2978
+ return None
2979
+
2920
2980
  return curlist[which_prof]
2981
+ else:
2982
+ logging.error(_('Dictionary %s not found in sorted dictionaries!')%which_dict)
2983
+ return None
2921
2984
 
2922
2985
  else:
2923
2986
  if isinstance(which_prof, str):
2924
2987
  keys = self.myprofiles.keys()
2925
2988
  if which_prof in keys:
2926
2989
  return self.myprofiles[which_prof]['cs']
2990
+ else:
2991
+ logging.error(_('Profile %s not found!')%which_prof)
2992
+ return None
2993
+
2927
2994
  elif isinstance(which_prof, int):
2995
+ if which_prof<0 or which_prof>=len(self.myprofiles):
2996
+ logging.error(_('Index %d out of range (0 to %d)!')%(which_prof,len(self.myprofiles)-1))
2997
+ return None
2998
+
2928
2999
  return self.myprofiles[list(self.myprofiles.keys())[which_prof]]['cs']
3000
+ else:
3001
+ logging.error(_('which_prof must be a string or an integer!'))
3002
+ return None
2929
3003
 
2930
3004
  return None
2931
3005
 
@@ -2961,6 +3035,103 @@ class crosssections(Element_To_Draw):
2961
3035
 
2962
3036
  self.cloud.find_minmax(True)
2963
3037
 
3038
+ def create_vector_from_centers(self, which_dict:str=None):
3039
+ """ Create a vector from the centers of the cross-sections."""
3040
+
3041
+ if which_dict is not None:
3042
+ if which_dict not in self.sorted.keys():
3043
+ logging.error(_('Dictionary %s not found in sorted dictionaries!')%which_dict)
3044
+ return vector(name='center', is2D=False)
3045
+
3046
+ curslist = self.sorted[which_dict]['sorted']
3047
+ centers = [curs.linestring.interpolate(0.5, normalized=True) for curs in curslist]
3048
+ else:
3049
+ centers = [curs['cs'].linestring.interpolate(0.5, normalized=True) for idx,curs in self.myprofiles.items()]
3050
+
3051
+ newvec = vector(name='center', is2D=False)
3052
+ newvec.add_vertex([wolfvertex(pt.x, pt.y) for pt in centers])
3053
+ return newvec
3054
+
3055
+ def create_vector_from_lefts(self, copy:bool=True, which_dict:str=None):
3056
+ """ Create a vector from the left (first vertex) of the cross-sections.
3057
+
3058
+ :param copy: If True, create a copy of the left vertices. If False, use the original vertices.
3059
+ :type copy: bool
3060
+ """
3061
+
3062
+ if which_dict is not None:
3063
+ if which_dict not in self.sorted.keys():
3064
+ logging.error(_('Dictionary %s not found in sorted dictionaries!')%which_dict)
3065
+ return vector(name='left', is2D=False)
3066
+
3067
+ curslist = self.sorted[which_dict]['sorted']
3068
+
3069
+ else:
3070
+ curslist = self.myprofiles.values()
3071
+
3072
+ if copy:
3073
+ lefts = [curs['cs'][0].copy() for curs in curslist]
3074
+ else:
3075
+ lefts = [curs['cs'][0] for curs in curslist]
3076
+
3077
+ newvec = vector(name='left', is2D=False)
3078
+ newvec.add_vertex(lefts)
3079
+ return newvec
3080
+
3081
+ def create_vector_from_rights(self, copy:bool=True, which_dict:str=None):
3082
+ """ Create a vector from the right (last vertex) of the cross-sections.
3083
+
3084
+ :param copy: If True, create a copy of the right vertices. If False, use the original vertices.
3085
+ :type copy: bool
3086
+ """
3087
+
3088
+ if which_dict is not None:
3089
+ if which_dict not in self.sorted.keys():
3090
+ logging.error(_('Dictionary %s not found in sorted dictionaries!')%which_dict)
3091
+ return vector(name='right', is2D=False)
3092
+
3093
+ curslist = self.sorted[which_dict]['sorted']
3094
+ else:
3095
+ curslist = self.myprofiles.values()
3096
+
3097
+ if copy:
3098
+ rights = [curs['cs'][-1].copy() for curs in curslist]
3099
+ else:
3100
+ rights = [curs['cs'][-1] for curs in curslist]
3101
+
3102
+ newvec = vector(name='right', is2D=False)
3103
+ newvec.add_vertex(rights)
3104
+ return newvec
3105
+
3106
+ def check_left_right_coherence(self):
3107
+ """ Check the coherence of left and right banks in the cross-sections.
3108
+
3109
+ :return: -2 if both banks intersect the center line, -1 if only left bank intersects, 1 if only right bank intersects, 0 if no intersection.
3110
+ :rtype: int
3111
+ """
3112
+
3113
+ center = self.create_vector_from_centers()
3114
+ left = self.create_vector_from_lefts(copy=False)
3115
+ right = self.create_vector_from_rights(copy=False)
3116
+
3117
+ # If the left bank intersects the center line, we have a problem.
3118
+ # If it is the case, the right bank must intersect the center line too.
3119
+
3120
+ if center.linestring.intersects(left.linestring):
3121
+ if not center.linestring.intersects(right.linestring):
3122
+ logging.warning(_('Left bank intersects the center line, but right bank does not!'))
3123
+ return -1
3124
+ else:
3125
+ logging.info(_('Left and right banks intersect the center line. Please check the profiles.'))
3126
+ return -2
3127
+ else:
3128
+ if center.linestring.intersects(right.linestring):
3129
+ logging.warning(_('Right bank intersects the center line, but left bank does not!'))
3130
+ return 1
3131
+ else:
3132
+ logging.info(_('Left and right banks do not intersect the center line.'))
3133
+ return 0
3134
+
2964
3135
  def create_zone_from_banksbed(self):
2965
3136
  """ Create a zone from the banks and bed of the cross-sections."""
2966
3137
 
@@ -3221,8 +3392,12 @@ class crosssections(Element_To_Draw):
3221
3392
 
3222
3393
  def get_upstream(self) -> dict['cs':profile, 'index':int, 'left':wolfvertex | None, 'bed':wolfvertex | None, 'right':wolfvertex | None, 'left_down':wolfvertex | None, 'right_down':wolfvertex | None]:
3223
3394
  """ Get the upstream profile of the cross-sections."""
3224
- curprof:profile
3225
- curprof=self.myprofiles[list(self.myprofiles.keys())[0]]['cs']
3395
+
3396
+ curprof = self[0]
3397
+
3398
+ if curprof.up is None:
3399
+ logging.warning(_('No upstream profile defined for profile %s.')%curprof.myname)
3400
+ return self.myprofiles[curprof.myname]
3226
3401
 
3227
3402
  while curprof.up is not curprof:
3228
3403
  curprof = curprof.up
@@ -3231,8 +3406,12 @@ class crosssections(Element_To_Draw):
3231
3406
 
3232
3407
  def get_downstream(self) -> dict['cs':profile, 'index':int, 'left':wolfvertex | None, 'bed':wolfvertex | None, 'right':wolfvertex | None, 'left_down':wolfvertex | None, 'right_down':wolfvertex | None]:
3233
3408
  """ Get the downstream profile of the cross-sections. """
3234
- curprof:profile
3235
- curprof=self.myprofiles[list(self.myprofiles.keys())[0]]['cs']
3409
+
3410
+ curprof = self[0]
3411
+
3412
+ if curprof.down is None:
3413
+ logging.warning(_('No downstream profile defined for profile %s.')%curprof.myname)
3414
+ return self.myprofiles[curprof.myname]
3236
3415
 
3237
3416
  while curprof.down is not curprof:
3238
3417
  curprof = curprof.down
@@ -3427,36 +3606,60 @@ class crosssections(Element_To_Draw):
3427
3606
 
3428
3607
  self.multils = self.asshapely_ls()
3429
3608
 
3430
- def sort_along(self,vecsupport:LineString,name:str,downfirst=True):
3609
+ def sort_along(self, vecsupport:LineString | vector, name:str, downfirst=True):
3431
3610
  """
3432
3611
  Sélectionne les sections qui intersectent un vecteur support
3433
3612
  et les trie selon l'abscisse curviligne
3434
3613
  """
3435
3614
 
3615
+ if isinstance(vecsupport, vector):
3616
+ vecsupport = vecsupport.linestring
3617
+ to_destroy = False
3618
+ elif isinstance(vecsupport, LineString):
3619
+ prepare(vecsupport) #Prepare le vecteur support aux opérations récurrentes
3620
+ to_destroy = True
3621
+ else:
3622
+ raise TypeError(_('vecsupport must be a LineString or a vector.'))
3623
+
3436
3624
  curdict = self.sorted[name]={}
3437
3625
  curdict['support'] = vecsupport
3438
3626
  mysorted = curdict['sorted'] = []
3439
3627
  length = vecsupport.length
3440
3628
 
3441
- prepare(vecsupport) #Prepare le vecteur support aux opérations récurrentes
3442
3629
  curvect:profile
3443
3630
  for idx,curv in self.myprofiles.items():
3444
3631
  #bouclage sur les sections
3445
3632
  curvect=curv['cs']
3446
3633
  #obtention de la section sous forme d'un objet Shapely
3447
- myline = curvect.asshapely_ls()
3634
+ myline = curvect.linestring
3448
3635
  if vecsupport.intersects(myline):
3449
- #le vecteur intersecte --> on calcule le point d'intersection
3636
+ # le vecteur intersecte --> on calcule le point d'intersection
3450
3637
  myintersect = vecsupport.intersection(myline)
3638
+
3639
+ if myintersect.geom_type=='MultiPoint':
3640
+ myintersect=myintersect.geoms[0]
3641
+ elif myintersect.geom_type=='GeometryCollection':
3642
+ myintersect=myintersect.centroid
3643
+
3451
3644
  #on projette l'intersection sur le support pour trouver l'abscisse curvi
3452
- mydist = vecsupport.project(myintersect)
3645
+ try:
3646
+ mydist = vecsupport.project(myintersect)
3647
+ except:
3648
+ pass
3649
+
3453
3650
  #on ajoute le vecteur à la liste
3454
3651
  mysorted.append(curvect)
3455
3652
  if downfirst:
3456
3653
  curvect.s = length - mydist
3457
3654
  else:
3458
3655
  curvect.s = mydist
3459
- destroy_prepared(vecsupport)
3656
+
3657
+ if to_destroy:
3658
+ destroy_prepared(vecsupport)
3659
+
3660
+ if len(mysorted)==0:
3661
+ logging.warning(_('No cross-section intersects the support vector!'))
3662
+ return 0
3460
3663
 
3461
3664
  #on trie le résultat en place
3462
3665
  mysorted.sort(key=lambda x:x.s)
wolfhece/PyDraw.py CHANGED
@@ -484,7 +484,7 @@ class Memory_Views_GUI(wx.Frame):
484
484
  self.CenterOnScreen()
485
485
 
486
486
  icon = wx.Icon()
487
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
487
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
488
488
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
489
489
  self.SetIcon(icon)
490
490
 
@@ -696,7 +696,7 @@ class Colors_1to9(wx.Frame):
696
696
  self.Bind(wx.EVT_BUTTON, self.OnSave, cmdSave)
697
697
 
698
698
  icon = wx.Icon()
699
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
699
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
700
700
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
701
701
  self.SetIcon(icon)
702
702
 
@@ -967,7 +967,7 @@ class Sim_Explorer(wx.Frame):
967
967
  self.Fit()
968
968
  self.Show()
969
969
 
970
- self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf_logo2.bmp")))
970
+ self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf.ico")))
971
971
 
972
972
  self._set_all(0)
973
973
 
@@ -1216,7 +1216,7 @@ class Sim_Explorer(wx.Frame):
1216
1216
 
1217
1217
  self._slider_steps.SetMax(nb)
1218
1218
  self._step_idx.Set([str(i) for i in range(1,nb+1)])
1219
- self._step_time.Set(['{:.3f} - {}'.format(i, datetime.strftime(self._starting_date + timedelta(seconds=i), '%Y-%m-%d %H:%M:%S')) for i in self._all_times_steps[0]])
1219
+ self._step_time.Set(['{:.3f} - {}'.format(i, datetime.strftime(self._starting_date + timedelta(seconds=float(i)), '%Y-%m-%d %H:%M:%S')) for i in self._all_times_steps[0]])
1220
1220
  self._step_num.Set([str(i) for i in self._all_times_steps[1]])
1221
1221
 
1222
1222
 
@@ -1338,7 +1338,7 @@ class Sim_VideoCreation(wx.Dialog):
1338
1338
  self.tc9.Bind(wx.EVT_CHOICE, self.OnValidate)
1339
1339
 
1340
1340
  icon = wx.Icon()
1341
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
1341
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
1342
1342
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
1343
1343
  self.SetIcon(icon)
1344
1344
  self.CenterOnScreen()
@@ -1516,7 +1516,7 @@ class Drowning_Explorer(wx.Frame):
1516
1516
  self.Fit()
1517
1517
  self.Show()
1518
1518
 
1519
- self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf_logo2.bmp")))
1519
+ self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf.ico")))
1520
1520
 
1521
1521
  self._set_all(0)
1522
1522
 
@@ -1800,7 +1800,7 @@ class Select_Begin_end_interval_step(wx.Dialog):
1800
1800
 
1801
1801
  self.CenterOnScreen()
1802
1802
 
1803
- self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf_logo2.bmp")))
1803
+ self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf.ico")))
1804
1804
 
1805
1805
  self.Show()
1806
1806
 
@@ -1930,7 +1930,7 @@ class Precomputed_DEM_DTM_Dialog(wx.Dialog):
1930
1930
 
1931
1931
  self.CenterOnScreen()
1932
1932
 
1933
- self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf_logo2.bmp")))
1933
+ self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf.ico")))
1934
1934
 
1935
1935
  self.Show()
1936
1936
 
@@ -13952,6 +13952,10 @@ class WolfMapViewer(wx.Frame):
13952
13952
  self.active_vector.find_minmax()
13953
13953
  self.active_zone.find_minmax()
13954
13954
 
13955
+ # Update the ogl list
13956
+ self.active_zone.reset_listogl()
13957
+ self.active_vector.reset_linestring()
13958
+
13955
13959
  elif self.action == 'offset/scale image':
13956
13960
 
13957
13961
  if self.active_vector is None:
@@ -14074,7 +14078,7 @@ class WolfMapViewer(wx.Frame):
14074
14078
  if self.active_vertex is None:
14075
14079
  self.active_vertex = self.active_vector.find_nearest_vert(x, y)
14076
14080
  else:
14077
- self.active_vertex.limit2bounds(self.active_vector.mylimits)
14081
+ self.active_vertex.limit2bounds(self.active_vector._mylimits)
14078
14082
 
14079
14083
  if ctrl:
14080
14084
  if self.active_array is not None:
@@ -14927,6 +14931,9 @@ class WolfMapViewer(wx.Frame):
14927
14931
  self.active_vector.myvertices[-1].x = x
14928
14932
  self.active_vector.myvertices[-1].y = y
14929
14933
 
14934
+ self.active_vector.reset_linestring()
14935
+ self.active_vector.parentzone.reset_listogl()
14936
+
14930
14937
  if self.action == 'modify vertices' or \
14931
14938
  self.action == 'insert vertices':
14932
14939
  if self.active_vertex is not None:
@@ -14955,7 +14962,7 @@ class WolfMapViewer(wx.Frame):
14955
14962
  self.active_vertex.x = x
14956
14963
  self.active_vertex.y = y
14957
14964
 
14958
- self.active_vertex.limit2bounds(self.active_vector.mylimits)
14965
+ self.active_vertex.limit2bounds(self.active_vector._mylimits)
14959
14966
 
14960
14967
  elif self.action == 'dynamic parallel':
14961
14968
  self.active_zone.parallel_active(self.dynapar_dist)
@@ -15544,7 +15551,7 @@ class WolfMapViewer(wx.Frame):
15544
15551
  frame.SetSizer(sizer)
15545
15552
 
15546
15553
  icon = wx.Icon()
15547
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
15554
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
15548
15555
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
15549
15556
  frame.SetIcon(icon)
15550
15557
 
wolfhece/PyGui.py CHANGED
@@ -168,7 +168,7 @@ class MapManager(GenMapManager):
168
168
 
169
169
  icon = wx.Icon()
170
170
 
171
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
171
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
172
172
 
173
173
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
174
174
 
@@ -1160,7 +1160,7 @@ if :\n \
1160
1160
  self.myprops.SetTitle(_('Vector properties - {}'.format(self.parent.myname)))
1161
1161
 
1162
1162
  icon = wx.Icon()
1163
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
1163
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
1164
1164
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
1165
1165
  self.myprops.SetIcon(icon)
1166
1166
 
@@ -1347,7 +1347,7 @@ class vector:
1347
1347
  self.xmax=-99999.
1348
1348
  self.ymax=-99999.
1349
1349
 
1350
- self.mylimits = None
1350
+ self._mylimits = None # ((xmin,xmax),(ymin,ymax)) --> Useful for wolf2dprev/block_contour objects
1351
1351
 
1352
1352
  self.textimage:Text_Image_Texture=None
1353
1353
 
@@ -1410,6 +1410,15 @@ class vector:
1410
1410
  if fromnumpy is not None:
1411
1411
  self.add_vertices_from_array(fromnumpy)
1412
1412
 
1413
+ def _set_limits(self):
1414
+ """ Retain current limits before any modification """
1415
+
1416
+ # Set self.minx, self.maxx), (self.miny, self.maxy)
1417
+ # on basis of the self.myvertices
1418
+
1419
+ self.find_minmax()
1420
+ self._mylimits = ((self.xmin, self.xmax), (self.ymin, self.ymax))
1421
+
1413
1422
  def __add__(self, other:"vector") -> "vector":
1414
1423
  """ Add two vectors together """
1415
1424
  if not isinstance(other, vector):
@@ -1892,6 +1901,9 @@ class vector:
1892
1901
  Conversion des coordonnées en Polygon Shapely
1893
1902
  """
1894
1903
 
1904
+ if self.nbvertices<3:
1905
+ return Polygon()
1906
+
1895
1907
  coords=self.asnparray()
1896
1908
  return Polygon(coords)
1897
1909
 
@@ -1900,6 +1912,9 @@ class vector:
1900
1912
  Conversion des coordonnées en Polygon Shapely
1901
1913
  """
1902
1914
 
1915
+ if self.nbvertices<3:
1916
+ return Polygon()
1917
+
1903
1918
  coords=self.asnparray3d()
1904
1919
  return Polygon(coords)
1905
1920
 
@@ -1972,9 +1987,12 @@ class vector:
1972
1987
 
1973
1988
  if prepare_shapely:
1974
1989
  if linestring:
1975
- prepare(self._linestring)
1990
+ if not self._linestring.is_empty:
1991
+ prepare(self._linestring)
1976
1992
  if polygon:
1977
- prepare(self._polygon)
1993
+ # Test if empty or not
1994
+ if not self._polygon.is_empty:
1995
+ prepare(self._polygon)
1978
1996
 
1979
1997
 
1980
1998
  def projectontrace(self, trace:"vector"):
@@ -2394,6 +2412,7 @@ class vector:
2394
2412
  """
2395
2413
 
2396
2414
  if self.nbvertices == 0:
2415
+ logging.debug(_('Vector {} has no vertices -- cannot create subpolygons').format(self.myname))
2397
2416
  return []
2398
2417
 
2399
2418
  if self.myprop.filled:
@@ -2414,26 +2433,30 @@ class vector:
2414
2433
  else:
2415
2434
  return [self.myvertices]
2416
2435
  else:
2417
- xx, yy = self.polygon.exterior.xy
2436
+ if self.polygon.area == 0:
2437
+ logging.debug(_('Vector {} has no area -- cannot create triangulation').format(self.myname))
2438
+ return []
2439
+ else:
2440
+ xx, yy = self.polygon.exterior.xy
2418
2441
 
2419
- # On translate les coordonnées pour éviter les erreurs de triangulation
2420
- tr_x = np.array(xx).min()
2421
- tr_y = np.array(yy).min()
2442
+ # On translate les coordonnées pour éviter les erreurs de triangulation
2443
+ tr_x = np.array(xx).min()
2444
+ tr_y = np.array(yy).min()
2422
2445
 
2423
- xx = np.array(xx)-tr_x
2424
- yy = np.array(yy)-tr_y
2446
+ xx = np.array(xx)-tr_x
2447
+ yy = np.array(yy)-tr_y
2425
2448
 
2426
- 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]]}
2449
+ 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]]}
2427
2450
 
2428
- try:
2429
- delaunay = triangle.triangulate(geom, 'p')
2430
- tri = []
2431
- for curtri in delaunay['triangles']:
2432
- # on traduit les coordonnées pour revenir dans le monde réel
2433
- tri.append([wolfvertex(delaunay['vertices'][curtri[i]][0] + tr_x, delaunay['vertices'][curtri[i]][1] + tr_y) for i in range(3)])
2434
- return tri
2435
- except:
2436
- pass
2451
+ try:
2452
+ delaunay = triangle.triangulate(geom, 'p')
2453
+ tri = []
2454
+ for curtri in delaunay['triangles']:
2455
+ # on traduit les coordonnées pour revenir dans le monde réel
2456
+ tri.append([wolfvertex(delaunay['vertices'][curtri[i]][0] + tr_x, delaunay['vertices'][curtri[i]][1] + tr_y) for i in range(3)])
2457
+ return tri
2458
+ except:
2459
+ pass
2437
2460
 
2438
2461
  else:
2439
2462
  if self.has_interior:
@@ -2585,7 +2608,7 @@ class vector:
2585
2608
 
2586
2609
  if self.myprop.filled:
2587
2610
 
2588
- ls = self.polygon
2611
+ # ls = self.polygon
2589
2612
 
2590
2613
  if False:
2591
2614
 
@@ -7912,7 +7935,7 @@ class Zones(wx.Frame, Element_To_Draw):
7912
7935
  self.SetSizer(box)
7913
7936
 
7914
7937
  icon = wx.Icon()
7915
- icon_path = Path(__file__).parent / "apps/wolf_logo2.bmp"
7938
+ icon_path = Path(__file__).parent / "apps/wolf.ico"
7916
7939
  icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
7917
7940
  self.SetIcon(icon)
7918
7941
 
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 2
8
- self.patch = 45
8
+ self.patch = 47
9
9
 
10
10
  def __str__(self):
11
11
 
wolfhece/apps/wolf.ico ADDED
Binary file
Binary file