wolfhece 2.2.33__py3-none-any.whl → 2.2.34__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.
@@ -705,10 +705,17 @@ class vectorproperties:
705
705
  self.attachedimage = None
706
706
  self.imagevisible = False
707
707
  self.textureimage:genericImagetexture = None
708
+ self.image_scale = 1.0
709
+ self.image_relative_posx = 0.0
710
+ self.image_relative_posy = 0.0
711
+ self.image_attached_pointx = -99999.
712
+ self.image_attached_pointy = -99999.
708
713
 
709
714
  self.plot_indices = False
710
715
 
711
- def get_extra(self) -> list[float,float,int,float,str,bool]:
716
+ self._cached_offset = None
717
+
718
+ def get_extra(self) -> list[float,float,int,float,str,bool, float, float, float, float, float]:
712
719
  """ Return extra properties """
713
720
  return [self.legendlength,
714
721
  self.legendheight,
@@ -716,9 +723,15 @@ class vectorproperties:
716
723
  self.legendorientation,
717
724
  str(self.attachedimage),
718
725
  self.imagevisible,
719
- self.plot_indices]
720
-
721
- def set_extra(self, linesextra:list[float,float,int,float,str,bool] = None):
726
+ self.plot_indices,
727
+ self.image_scale,
728
+ self.image_relative_posx,
729
+ self.image_relative_posy,
730
+ self.image_attached_pointx,
731
+ self.image_attached_pointy
732
+ ]
733
+
734
+ def set_extra(self, linesextra:list[float,float,int,float,str,bool, float, float, float, float, float] = None):
722
735
  """ Set extra properties """
723
736
 
724
737
  if linesextra is None:
@@ -728,7 +741,7 @@ class vectorproperties:
728
741
 
729
742
  self.legendlength = float(linesextra[0])
730
743
  self.legendheight = float(linesextra[1])
731
- self.legendpriority = float(linesextra[2])
744
+ self.legendpriority = int(linesextra[2])
732
745
  self.legendorientation = float(linesextra[3])
733
746
 
734
747
  if len(linesextra)>4:
@@ -738,6 +751,13 @@ class vectorproperties:
738
751
  if len(linesextra)>6:
739
752
  self.plot_indices = linesextra[6].lower() == 'true'
740
753
 
754
+ if len(linesextra)>7:
755
+ self.image_scale = float(linesextra[7])
756
+ self.image_relative_posx = float(linesextra[8])
757
+ self.image_relative_posy = float(linesextra[9])
758
+ self.image_attached_pointx = float(linesextra[10])
759
+ self.image_attached_pointy = float(linesextra[11])
760
+
741
761
  def load_extra(self, lines:list[str]) -> int:
742
762
  """ Load extra properties from lines """
743
763
 
@@ -802,6 +822,18 @@ class vectorproperties:
802
822
 
803
823
  (xmin,xmax),(ymin,ymax) = self.parent.get_bounds_xx_yy()
804
824
 
825
+ if self.textureimage is not None:
826
+ if self.textureimage.imageFile == self.attachedimage:
827
+ self.textureimage.drawing_scale = self.image_scale
828
+ self.textureimage.offset = (self.image_relative_posx, self.image_relative_posy)
829
+ self.textureimage.xmin = xmin
830
+ self.textureimage.xmax = xmax
831
+ self.textureimage.ymin = ymin
832
+ self.textureimage.ymax = ymax
833
+ return
834
+ else:
835
+ self.textureimage.unload()
836
+
805
837
  self.textureimage = genericImagetexture(which = 'attachedfile',
806
838
  label=self.parent.myname,
807
839
  mapviewer= self.parent.get_mapviewer(),
@@ -809,8 +841,9 @@ class vectorproperties:
809
841
  xmin=xmin,
810
842
  xmax=xmax,
811
843
  ymin=ymin,
812
- ymax=ymax)
813
- # self.textureimage.load(str(self.textureimage))
844
+ ymax=ymax,
845
+ drawing_scale= self.image_scale,
846
+ offset = (self.image_relative_posx, self.image_relative_posy))
814
847
  else:
815
848
  logging.warning('Image not found : {}'.format(self.attachedimage))
816
849
  else:
@@ -865,6 +898,11 @@ class vectorproperties:
865
898
 
866
899
  self.attachedimage = Path(props[('Image','Attached image')])
867
900
  self.imagevisible = props[('Image','To show')]
901
+ self.image_scale = props[('Image','Scale')]
902
+ self.image_relative_posx = props[('Image','Relative position X')]
903
+ self.image_relative_posy = props[('Image','Relative position Y')]
904
+ self.image_attached_pointx = props[('Image','Attached point X')]
905
+ self.image_attached_pointy = props[('Image','Attached point Y')]
868
906
 
869
907
  posx = props[('Move','Start X')]
870
908
  posy = props[('Move','Start Y')]
@@ -1008,6 +1046,11 @@ if :\n \
1008
1046
 
1009
1047
  self.myprops.addparam('Image','Attached image','',Type_Param.File, '', whichdict='Default')
1010
1048
  self.myprops.addparam('Image','To show',False,Type_Param.Logical,'',whichdict='Default')
1049
+ self.myprops.addparam('Image','Scale',1.0,Type_Param.Float,'',whichdict='Default')
1050
+ self.myprops.addparam('Image','Relative position X',0.0,Type_Param.Float,'',whichdict='Default')
1051
+ self.myprops.addparam('Image','Relative position Y',0.0,Type_Param.Float,'',whichdict='Default')
1052
+ self.myprops.addparam('Image','Attached point X',-99999.,Type_Param.Float,'',whichdict='Default')
1053
+ self.myprops.addparam('Image','Attached point Y',-99999.,Type_Param.Float,'',whichdict='Default')
1011
1054
 
1012
1055
  def destroyprop(self):
1013
1056
  """
@@ -1113,6 +1156,11 @@ if :\n \
1113
1156
 
1114
1157
  self.myprops[('Image','Attached image')] = str(self.attachedimage)
1115
1158
  self.myprops[('Image','To show')] = self.imagevisible
1159
+ self.myprops[('Image','Scale')] = self.image_scale
1160
+ self.myprops[('Image','Relative position X')] = self.image_relative_posx
1161
+ self.myprops[('Image','Relative position Y')] = self.image_relative_posy
1162
+ self.myprops[('Image','Attached point X')] = self.image_attached_pointx
1163
+ self.myprops[('Image','Attached point Y')] = self.image_attached_pointy
1116
1164
 
1117
1165
  if self.parent._rotation_center is not None:
1118
1166
  self.myprops[('Rotation','center X')] = self.parent._rotation_center[0]
@@ -1144,6 +1192,31 @@ if :\n \
1144
1192
  self.myprops[('Move','Delta Y')] = 0.
1145
1193
 
1146
1194
  self.myprops.Populate()
1195
+
1196
+ def update_image_texture(self):
1197
+ """ Update the image texture if it exists """
1198
+ if self.textureimage is not None:
1199
+ (xmin, xmax), (ymin, ymax) = self.parent.get_bounds_xx_yy()
1200
+ self.textureimage.xmin = xmin
1201
+ self.textureimage.xmax = xmax
1202
+ self.textureimage.ymin = ymin
1203
+ self.textureimage.ymax = ymax
1204
+ self.textureimage.drawing_scale = self.image_scale
1205
+ self.textureimage.offset = (self.image_relative_posx, self.image_relative_posy)
1206
+
1207
+ def _offset_image_texture(self, delta_x:float, delta_y:float):
1208
+ """ Offset the image texture by a delta in x and y direction """
1209
+
1210
+ if self._cached_offset is None:
1211
+ self._cached_offset = (self.image_relative_posx, self.image_relative_posy)
1212
+
1213
+ self.image_relative_posx = self._cached_offset[0] + delta_x
1214
+ self.image_relative_posy = self._cached_offset[1] + delta_y
1215
+
1216
+ def _reset_cached_offset(self):
1217
+ """ Reset the cached offset for the image texture """
1218
+ self._cached_offset = None
1219
+
1147
1220
  class vector:
1148
1221
  """
1149
1222
  Objet de gestion d'informations vectorielles
@@ -1419,11 +1492,13 @@ class vector:
1419
1492
  """ Set the cache for the vertices """
1420
1493
 
1421
1494
  self._cache_vertices = self.asnparray3d()
1495
+ self._cache_bounds = np.array([[self.xmin, self.xmax], [self.ymin, self.ymax]])
1422
1496
 
1423
1497
  def clear_cache(self):
1424
1498
  """ Clear the cache for the vertices """
1425
1499
 
1426
1500
  self._cache_vertices = None
1501
+ self._cache_bounds = None
1427
1502
 
1428
1503
  def move(self, deltax:float, deltay:float, use_cache:bool = True, inplace:bool = True):
1429
1504
  """
@@ -1445,10 +1520,26 @@ class vector:
1445
1520
 
1446
1521
  if use_cache:
1447
1522
  self.xy = self._cache_vertices[:,:2] + np.array([deltax, deltay])
1523
+ self.xmin = self._cache_bounds[0,0] + deltax
1524
+ self.xmax = self._cache_bounds[0,1] + deltax
1525
+ self.ymin = self._cache_bounds[1,0] + deltay
1526
+ self.ymax = self._cache_bounds[1,1] + deltay
1448
1527
  else:
1449
1528
  for curvert in self.myvertices:
1450
1529
  curvert.x += deltax
1451
1530
  curvert.y += deltay
1531
+ # update the bounds
1532
+ self.xmin += deltax
1533
+ self.xmax += deltax
1534
+ self.ymin += deltay
1535
+ self.ymax += deltay
1536
+
1537
+ # update the texture image position if it exists
1538
+ if self.myprop.textureimage is not None:
1539
+ self.myprop.textureimage.xmin = self.xmin
1540
+ self.myprop.textureimage.xmax = self.xmax
1541
+ self.myprop.textureimage.ymin = self.ymin
1542
+ self.myprop.textureimage.ymax = self.ymax
1452
1543
 
1453
1544
  return self
1454
1545
  else:
@@ -1482,6 +1573,14 @@ class vector:
1482
1573
  for curvert in self.myvertices:
1483
1574
  curvert.rotate(angle, center)
1484
1575
 
1576
+ self.find_minmax()
1577
+
1578
+ if self.myprop.textureimage is not None:
1579
+ self.myprop.textureimage.xmin = self.xmin
1580
+ self.myprop.textureimage.xmax = self.xmax
1581
+ self.myprop.textureimage.ymin = self.ymin
1582
+ self.myprop.textureimage.ymax = self.ymax
1583
+
1485
1584
  return self
1486
1585
  else:
1487
1586
  new_vector = self.deepcopy_vector(self.myname + '_rotated')
@@ -2071,6 +2170,13 @@ class vector:
2071
2170
 
2072
2171
  return self.myvertices[indexmp]
2073
2172
 
2173
+ def update_image_texture(self):
2174
+ """
2175
+ Met à jour la texture de l'image si elle existe
2176
+ """
2177
+
2178
+ self.myprop.update_image_texture()
2179
+
2074
2180
  def find_minmax(self, only_firstlast:bool=False):
2075
2181
  """
2076
2182
  Recherche l'extension spatiale du vecteur
@@ -2090,6 +2196,8 @@ class vector:
2090
2196
  self.ymin=min(vert.y for vert in self.myvertices)
2091
2197
  self.xmax=max(vert.x for vert in self.myvertices)
2092
2198
  self.ymax=max(vert.y for vert in self.myvertices)
2199
+
2200
+ self.update_image_texture()
2093
2201
  else:
2094
2202
  self.xmin=-99999.
2095
2203
  self.ymin=-99999.
@@ -4135,14 +4243,14 @@ class zone:
4135
4243
  self.has_legend |= curvect.myprop.legendvisible
4136
4244
  self.has_image |= curvect.myprop.imagevisible
4137
4245
 
4138
- if self.has_legend:
4139
- for curvect in self.myvectors:
4140
- curvect.plot_legend(sx, sy, xmin, ymin, xmax, ymax, size)
4141
-
4142
4246
  if self.has_image:
4143
4247
  for curvect in self.myvectors:
4144
4248
  curvect.plot_image(sx, sy, xmin, ymin, xmax, ymax, size)
4145
4249
 
4250
+ if self.has_legend:
4251
+ for curvect in self.myvectors:
4252
+ curvect.plot_legend(sx, sy, xmin, ymin, xmax, ymax, size)
4253
+
4146
4254
  def plot_matplotlib(self, ax:plt.Axes):
4147
4255
  """
4148
4256
  Plot the zone using matplotlib
@@ -6725,6 +6833,14 @@ class Zones(wx.Frame, Element_To_Draw):
6725
6833
 
6726
6834
  return minvec
6727
6835
 
6836
+ def find_vector_containing_point(self, x:float, y:float) -> vector:
6837
+ """ Trouve le prmier vecteur contenant le point (x,y) """
6838
+ xy = Point(x, y)
6839
+ for curzone in self.myzones:
6840
+ for curvect in curzone.myvectors:
6841
+ if curvect.polygon.contains(xy):
6842
+ return curvect
6843
+
6728
6844
  def reset_listogl(self):
6729
6845
  """
6730
6846
  Reset des listes OpenGL pour toutes les zones
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 = 33
8
+ self.patch = 34
9
9
 
10
10
  def __str__(self):
11
11
 
wolfhece/textpillow.py CHANGED
@@ -194,7 +194,7 @@ class Text_Infos():
194
194
  elif self.priority == Font_Priority.HEIGHT:
195
195
  self.fontsize = int(self.fontsize/scaley)
196
196
 
197
- self.fontsize=min(self.fontsize,200)
197
+ self.fontsize=max(min(self.fontsize,200),2)
198
198
 
199
199
  self.findsize(text)
200
200
 
wolfhece/wolf_texture.py CHANGED
@@ -48,12 +48,32 @@ class genericImagetexture(Element_To_Draw):
48
48
  which: str,
49
49
  label: str,
50
50
  mapviewer,
51
- xmin, xmax, ymin, ymax,
52
- imageFile="",
53
- imageObj=None,
51
+ xmin:float, xmax:float, ymin:float, ymax:float,
52
+ imageFile:str = "",
53
+ imageObj = None,
54
54
  transparent_color = None,
55
55
  tolerance:int = 3,
56
- replace_color = None) -> None:
56
+ replace_color = None,
57
+ drawing_scale:float = 1.0,
58
+ offset:list[float, float] = [0.,0.]) -> None:
59
+
60
+ """ Initialize the image texture
61
+
62
+ :param which: Type of image (e.g., 'satellite', 'map', etc.)
63
+ :param label: Label for the texture
64
+ :param mapviewer: The map viewer object to which this texture belongs
65
+ :param xmin: Minimum X coordinate for the texture
66
+ :param xmax: Maximum X coordinate for the texture
67
+ :param ymin: Minimum Y coordinate for the texture
68
+ :param ymax: Maximum Y coordinate for the texture
69
+ :param imageFile: Optional file path to load the image from
70
+ :param imageObj: Optional PIL Image object to use instead of loading from file
71
+ :param transparent_color: Color to treat as transparent in the image
72
+ :param tolerance: Tolerance for color matching when replacing transparent color
73
+ :param replace_color: Color to replace the transparent color with
74
+ :param drawing_scale: Scale factor for the image
75
+ :param offset: Offset to apply to the texture position
76
+ """
57
77
 
58
78
  super().__init__(label, True, mapviewer, False)
59
79
 
@@ -61,6 +81,7 @@ class genericImagetexture(Element_To_Draw):
61
81
  self.mapviewer.canvas.SetCurrent(mapviewer.context)
62
82
  except:
63
83
  logging.error(_('Opengl setcurrent -- Do you have a active canvas ?'))
84
+ return
64
85
 
65
86
  self.time = None
66
87
  self.xmin = xmin
@@ -82,6 +103,9 @@ class genericImagetexture(Element_To_Draw):
82
103
  self.imageFile = imageFile
83
104
  self.myImage = imageObj
84
105
 
106
+ self.drawing_scale = drawing_scale
107
+ self.offset = offset
108
+
85
109
  if imageFile != "":
86
110
  if exists(imageFile):
87
111
  try:
@@ -142,6 +166,11 @@ class genericImagetexture(Element_To_Draw):
142
166
  del self.myImage
143
167
 
144
168
  def load(self, imageFile=""):
169
+ """ Load the image texture into OpenGL
170
+
171
+ :param imageFile: Optional file path to load the image from
172
+ """
173
+
145
174
  if self.width == -99999 or self.height == -99999:
146
175
  return
147
176
 
@@ -167,6 +196,7 @@ class genericImagetexture(Element_To_Draw):
167
196
  'Opengl setcurrent -- maybe a conflict with an existing opengl32.dll file - please rename the opengl32.dll in the libs directory and retry')
168
197
 
169
198
  def update_minmax(self):
199
+ """ Update the spatial extent of the texture based on its size """
170
200
 
171
201
  if self.myImage is None:
172
202
  return
@@ -181,7 +211,7 @@ class genericImagetexture(Element_To_Draw):
181
211
 
182
212
  self.ymax = self.ymin + dx *scale
183
213
 
184
- def reload(self,xmin=-99999,xmax=-99999,ymin=-99999,ymax=-99999):
214
+ def reload(self, xmin=-99999, xmax=-99999, ymin=-99999, ymax=-99999):
185
215
 
186
216
  if xmin !=-99999:
187
217
  self.xmin = xmin
@@ -210,7 +240,28 @@ class genericImagetexture(Element_To_Draw):
210
240
  # Nothing to do, set during initialization phase
211
241
  pass
212
242
 
243
+ def uv(self, x: float, y: float) -> tuple[float, float]:
244
+ """ Convert coordinates to texture coordinates taking into account the texture's spatial extent,
245
+ the scaleing factor, and the offset.
246
+
247
+ :param x: X coordinate in pixels
248
+ :param y: Y coordinate in pixels
249
+ :return: Tuple of (u, v) texture coordinates
250
+ """
251
+ if self.width == -99999 or self.height == -99999:
252
+ return 0.0, 0.0
253
+
254
+ u = (x - self.offset[0] - self.xmin) / ((self.xmax - self.xmin) * self.drawing_scale)
255
+ v = 1.0 - (y - self.offset[1] - self.ymin) / ((self.ymax - self.ymin) * self.drawing_scale)
256
+
257
+ # Ensure u and v are within the range [0, 1]
258
+ u = max(0.0, min(1.0, u))
259
+ v = max(0.0, min(1.0, v))
260
+
261
+ return u, v
262
+
213
263
  def paint(self):
264
+ """ Paint the image texture on the OpenGL canvas """
214
265
 
215
266
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
216
267
 
@@ -222,14 +273,31 @@ class genericImagetexture(Element_To_Draw):
222
273
  glBindTexture(GL_TEXTURE_2D, self.idtexture[0])
223
274
 
224
275
  glBegin(GL_QUADS)
225
- glTexCoord2f(0.0, 0.0)
226
- glVertex2f(self.xmin, self.ymax)
227
- glTexCoord2f(1.0, 0.0)
228
- glVertex2f(self.xmax, self.ymax)
229
- glTexCoord2f(1.0, 1.0)
230
- glVertex2f(self.xmax, self.ymin)
231
- glTexCoord2f(0.0, 1.0)
232
- glVertex2f(self.xmin, self.ymin)
276
+
277
+ # Draw a quad with texture coordinates
278
+ xy = [[self.xmin, self.ymax],
279
+ [self.xmax, self.ymax],
280
+ [self.xmax, self.ymin],
281
+ [self.xmin, self.ymin]]
282
+ uv = [self.uv(x,y) for x,y in xy]
283
+
284
+ glTexCoord2f(uv[0][0], uv[0][1])
285
+ glVertex2f(xy[0][0], xy[0][1])
286
+ glTexCoord2f(uv[1][0], uv[1][1])
287
+ glVertex2f(xy[1][0], xy[1][1])
288
+ glTexCoord2f(uv[2][0], uv[2][1])
289
+ glVertex2f(xy[2][0], xy[2][1])
290
+ glTexCoord2f(uv[3][0], uv[3][1])
291
+ glVertex2f(xy[3][0], xy[3][1])
292
+
293
+ # glTexCoord2f(0.0, 0.0)
294
+ # glVertex2f(self.xmin, self.ymax)
295
+ # glTexCoord2f(1.0, 0.0)
296
+ # glVertex2f(self.xmax, self.ymax)
297
+ # glTexCoord2f(1.0, 1.0)
298
+ # glVertex2f(self.xmax, self.ymin)
299
+ # glTexCoord2f(0.0, 1.0)
300
+ # glVertex2f(self.xmin, self.ymin)
233
301
  glEnd()
234
302
  glDisable(GL_TEXTURE_2D)
235
303
  glDisable(GL_BLEND)