wolfhece 2.2.17__py3-none-any.whl → 2.2.20__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.
- wolfhece/PyDraw.py +75 -10
- wolfhece/PyGui.py +6 -0
- wolfhece/PyVertexvectors.py +233 -23
- wolfhece/Results2DGPU.py +14 -2
- wolfhece/__init__.py +14 -1
- wolfhece/analyze_poly.py +335 -0
- wolfhece/apps/version.py +1 -1
- wolfhece/assets/tree.py +0 -0
- wolfhece/lazviewer/__init__.py +21 -12
- wolfhece/mesh2d/bc_manager.py +1 -1
- wolfhece/mesh2d/cst_2D_boundary_conditions.py +1 -1
- wolfhece/mesh2d/gpu_2d.py +46 -10
- wolfhece/mesh2d/simple_2d.py +94 -69
- wolfhece/mesh2d/wolf2dprev.py +12 -0
- wolfhece/os_check.py +16 -0
- wolfhece/pydike.py +245 -41
- wolfhece/scenario/config_manager.py +13 -0
- wolfhece/tools2d_dll.py +6 -0
- wolfhece/wolf_array.py +392 -48
- wolfhece/wolf_texture.py +1 -0
- wolfhece/wolfresults_2D.py +23 -1
- {wolfhece-2.2.17.dist-info → wolfhece-2.2.20.dist-info}/METADATA +1 -1
- {wolfhece-2.2.17.dist-info → wolfhece-2.2.20.dist-info}/RECORD +26 -23
- {wolfhece-2.2.17.dist-info → wolfhece-2.2.20.dist-info}/WHEEL +1 -1
- {wolfhece-2.2.17.dist-info → wolfhece-2.2.20.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.2.17.dist-info → wolfhece-2.2.20.dist-info}/top_level.txt +0 -0
wolfhece/PyDraw.py
CHANGED
@@ -2077,7 +2077,7 @@ class WolfMapViewer(wx.Frame):
|
|
2077
2077
|
self.popupmenu = wx.Menu()
|
2078
2078
|
self.popupmenu.Bind(wx.EVT_MENU, self.OnPopupItemSelected)
|
2079
2079
|
|
2080
|
-
for text in [_('Save'), _('Save as'), _('Rename'), _('Duplicate'), _('Delete'), _('Up'), _('Down'), _('Check/Uncheck'), _('Properties')]:
|
2080
|
+
for text in [_('Save'), _('Save as'), _('Rename'), _('Duplicate'), _('Delete'), _('Up'), _('Down'), _('Check/Uncheck'), _('Properties'), _('Reload')]:
|
2081
2081
|
item = self.popupmenu.Append(-1, text)
|
2082
2082
|
|
2083
2083
|
self.menubar = wx.MenuBar()
|
@@ -2295,9 +2295,9 @@ class WolfMapViewer(wx.Frame):
|
|
2295
2295
|
|
2296
2296
|
self.analyzeplot.AppendSeparator()
|
2297
2297
|
|
2298
|
-
self.analyzemenu.Append(wx.ID_ANY,_('Plot...'),self.analyzeplot)
|
2299
|
-
self.analyzemenu.Append(wx.ID_ANY,_('Export...'),self.analyzeexport)
|
2300
|
-
self.analyzemenu.Append(wx.ID_ANY,_('Inpaint...'),self.analyzeinpaint)
|
2298
|
+
self.analyzemenu.Append(wx.ID_ANY,_('Plot...'), self.analyzeplot)
|
2299
|
+
self.analyzemenu.Append(wx.ID_ANY,_('Export...'), self.analyzeexport)
|
2300
|
+
self.analyzemenu.Append(wx.ID_ANY,_('Inpaint...'), self.analyzeinpaint)
|
2301
2301
|
|
2302
2302
|
|
2303
2303
|
self.analyzeinpaint.Append(wx.ID_ANY, _("Inpaint active array..."), _("Inpaint active array"))
|
@@ -2700,12 +2700,19 @@ class WolfMapViewer(wx.Frame):
|
|
2700
2700
|
self.trianglesmenu = wx.Menu()
|
2701
2701
|
self.menubar.Append(self.trianglesmenu, _('&Triangulations'))
|
2702
2702
|
|
2703
|
-
self._menuinteractptri = self.trianglesmenu.Append(wx.ID_ANY, _("Interpolate on active triangulation..."),
|
2703
|
+
self._menuinteractptri = self.trianglesmenu.Append(wx.ID_ANY, _("Interpolate on active triangulation..."),
|
2704
|
+
_('Interpolate active array on active triangulation'))
|
2705
|
+
|
2706
|
+
self._menuinteractptri_above = self.trianglesmenu.Append(wx.ID_ANY, _("Interpolate on active triangulation (keep only above)..."),
|
2707
|
+
_('Interpolate active array on active triangulation but keep only values above the array'))
|
2708
|
+
|
2709
|
+
self._menuinteractptri_below = self.trianglesmenu.Append(wx.ID_ANY, _("Interpolate on active triangulation (keep only below)..."),
|
2710
|
+
_('Interpolate active array on active triangulation but keep only values below the array'))
|
2711
|
+
|
2704
2712
|
self._menucomparetri = self.trianglesmenu.Append(wx.ID_ANY, _("Compare triangles to array..."), _("Comparison"))
|
2705
2713
|
self._menumovetri = self.trianglesmenu.Append(wx.ID_ANY, _("Move triangles..."), _("Move triangles"))
|
2706
2714
|
self._menurotatetri = self.trianglesmenu.Append(wx.ID_ANY, _("Rotate triangles..."), _("Rotate triangles"))
|
2707
2715
|
|
2708
|
-
|
2709
2716
|
def create_cloud_menu(self):
|
2710
2717
|
""" Menu for cloud points """
|
2711
2718
|
|
@@ -3001,6 +3008,29 @@ class WolfMapViewer(wx.Frame):
|
|
3001
3008
|
|
3002
3009
|
return [xmin, ymin, xmax, ymax]
|
3003
3010
|
|
3011
|
+
def get_bounds(self):
|
3012
|
+
"""
|
3013
|
+
Retourne les limites de la zone d'affichage, voir aussi get_canvas_bounds
|
3014
|
+
|
3015
|
+
:return: ([xmin, xmax], [ymin, ymax])
|
3016
|
+
"""
|
3017
|
+
xmin, ymin, xmax, ymax = self.get_canvas_bounds()
|
3018
|
+
return ([xmin, xmax], [ymin, ymax])
|
3019
|
+
|
3020
|
+
def get_bounds_as_polygon(self) -> vector:
|
3021
|
+
"""
|
3022
|
+
Retourne les limites de la zone d'affichage sous forme de polygone
|
3023
|
+
:return: vector
|
3024
|
+
"""
|
3025
|
+
xmin, ymin, xmax, ymax = self.get_canvas_bounds()
|
3026
|
+
poly = vector()
|
3027
|
+
poly.add_vertex(wolfvertex(xmin, ymin))
|
3028
|
+
poly.add_vertex(wolfvertex(xmax, ymin))
|
3029
|
+
poly.add_vertex(wolfvertex(xmax, ymax))
|
3030
|
+
poly.add_vertex(wolfvertex(xmin, ymax))
|
3031
|
+
poly.force_to_close()
|
3032
|
+
return poly
|
3033
|
+
|
3004
3034
|
def Onmenuwalous(self, event: wx.MenuEvent):
|
3005
3035
|
|
3006
3036
|
id = event.GetId()
|
@@ -4390,7 +4420,11 @@ class WolfMapViewer(wx.Frame):
|
|
4390
4420
|
|
4391
4421
|
self.myinterp.interp_on_array(self.active_array, method)
|
4392
4422
|
|
4393
|
-
def interpolate_triangulation(self):
|
4423
|
+
def interpolate_triangulation(self, keep:Literal['all', 'above', 'below'] = 'all'):
|
4424
|
+
""" Alias to interpolate on triangulation
|
4425
|
+
|
4426
|
+
:param keep: 'all' to keep all points, 'above' to keep only points above the current array's value, 'below' to keep only points below the current array's value
|
4427
|
+
"""
|
4394
4428
|
|
4395
4429
|
if self.active_array is None:
|
4396
4430
|
logging.warning(_('No active array -- Please activate an array first'))
|
@@ -4400,7 +4434,7 @@ class WolfMapViewer(wx.Frame):
|
|
4400
4434
|
logging.warning(_('No active triangulation -- Please activate a triangulation first'))
|
4401
4435
|
return
|
4402
4436
|
|
4403
|
-
self.active_array.interpolate_on_triangulation(self.active_tri.pts, self.active_tri.tri, )
|
4437
|
+
self.active_array.interpolate_on_triangulation(self.active_tri.pts, self.active_tri.tri, keep=keep)
|
4404
4438
|
|
4405
4439
|
def compare_cloud2array(self):
|
4406
4440
|
"""
|
@@ -8429,7 +8463,13 @@ class WolfMapViewer(wx.Frame):
|
|
8429
8463
|
# self.import_3dfaces()
|
8430
8464
|
|
8431
8465
|
elif itemlabel == _("Interpolate on active triangulation..."):
|
8432
|
-
self.interpolate_triangulation()
|
8466
|
+
self.interpolate_triangulation(keep='all')
|
8467
|
+
|
8468
|
+
elif itemlabel == _("Interpolate on active triangulation (keep only above)..."):
|
8469
|
+
self.interpolate_triangulation(keep='above')
|
8470
|
+
|
8471
|
+
elif itemlabel == _("Interpolate on active triangulation (keep only below)..."):
|
8472
|
+
self.interpolate_triangulation(keep='below')
|
8433
8473
|
|
8434
8474
|
elif itemlabel==_("Compare cloud to array..."):
|
8435
8475
|
self.compare_cloud2array()
|
@@ -11565,6 +11605,31 @@ class WolfMapViewer(wx.Frame):
|
|
11565
11605
|
|
11566
11606
|
dlg.Destroy()
|
11567
11607
|
|
11608
|
+
elif _('Reload') in text:
|
11609
|
+
|
11610
|
+
if isinstance(self.selected_object, WolfArray):
|
11611
|
+
if self.selected_object.filename is not None:
|
11612
|
+
|
11613
|
+
dlg = wx.MessageDialog(None, _('Do you want to reload the file ?'), _('Reload'), wx.YES_NO | wx.NO_DEFAULT)
|
11614
|
+
ret = dlg.ShowModal()
|
11615
|
+
if ret == wx.ID_YES:
|
11616
|
+
self.selected_object.read_all()
|
11617
|
+
self.selected_object.mask_data(self.selected_object.nullvalue)
|
11618
|
+
self.selected_object.reset_plot()
|
11619
|
+
|
11620
|
+
dlg.Destroy()
|
11621
|
+
# elif isinstance(self.selected_object, Zones):
|
11622
|
+
# if self.selected_object.filename is not None:
|
11623
|
+
# dlg = wx.MessageDialog(None, _('Do you want to reload the file ?'), _('Reload'), wx.YES_NO | wx.NO_DEFAULT)
|
11624
|
+
# ret = dlg.ShowModal()
|
11625
|
+
# if ret == wx.ID_YES:
|
11626
|
+
# self.selected_object.read()
|
11627
|
+
|
11628
|
+
# dlg.Destroy()
|
11629
|
+
|
11630
|
+
else:
|
11631
|
+
logging.warning(_('Reload not yet implemented for this type of object'))
|
11632
|
+
|
11568
11633
|
def OnClose(self, event):
|
11569
11634
|
""" Close the application """
|
11570
11635
|
|
@@ -13144,7 +13209,7 @@ class WolfMapViewer(wx.Frame):
|
|
13144
13209
|
width, height = self.canvas.GetSize()
|
13145
13210
|
|
13146
13211
|
if iwidth == 0 or iheight == 0:
|
13147
|
-
logging.
|
13212
|
+
logging.warning(_('Width or height of the canvas is null -- Please check the "findminmax" routine in "Autoscale" !'))
|
13148
13213
|
iwidth = 1
|
13149
13214
|
iheight = 1
|
13150
13215
|
|
wolfhece/PyGui.py
CHANGED
@@ -2915,6 +2915,12 @@ class Wolf2DGPUModel(GenMapManager):
|
|
2915
2915
|
if force_reload:
|
2916
2916
|
self._sim.reload_all()
|
2917
2917
|
for cur in self.arrays.values():
|
2918
|
+
|
2919
|
+
if cur.idx == 'water surface elevation [m]':
|
2920
|
+
## Force to recompute the water surface elevation
|
2921
|
+
cur.array.data[:,:] = self.arrays['bathymetry'].array.data[:,:] + self.arrays['h'].array.data[:,:]
|
2922
|
+
cur.array.mask[:,:] = self.arrays['bathymetry'].array.mask[:,:]
|
2923
|
+
|
2918
2924
|
cur.reset_plot()
|
2919
2925
|
# self.mapviewer.Refresh()
|
2920
2926
|
else:
|
wolfhece/PyVertexvectors.py
CHANGED
@@ -27,6 +27,7 @@ from matplotlib.axes import Axes
|
|
27
27
|
from matplotlib.figure import Figure
|
28
28
|
from matplotlib import cm
|
29
29
|
from matplotlib.colors import Colormap
|
30
|
+
from matplotlib.tri import Triangulation as mpl_tri
|
30
31
|
|
31
32
|
import struct
|
32
33
|
import pyvista as pv
|
@@ -414,6 +415,22 @@ class Triangulation(Element_To_Draw):
|
|
414
415
|
else:
|
415
416
|
logging.warning('No triangles to plot')
|
416
417
|
|
418
|
+
@property
|
419
|
+
def mpl_triangulation(self) -> mpl_tri:
|
420
|
+
""" Return the triangulation as a Matplotlib Triangulation object """
|
421
|
+
if self.nb_tri>0:
|
422
|
+
return mpl_tri(self.pts[:,0], self.pts[:,1], self.tri)
|
423
|
+
else:
|
424
|
+
logging.warning('No triangles to plot')
|
425
|
+
return None
|
426
|
+
|
427
|
+
def plot_matplotlib_3D(self, ax:Axes, color='black', alpha=0.2, lw=1.5, edgecolor='k', shade=True, **kwargs):
|
428
|
+
""" Plot the triangulation in Matplotlib 3D
|
429
|
+
"""
|
430
|
+
if self.nb_tri>0:
|
431
|
+
ax.plot_trisurf(self.mpl_triangulation, Z=self.pts[:,2], color=color, alpha=alpha, lw=lw, edgecolor=edgecolor, shade=shade, **kwargs)
|
432
|
+
else:
|
433
|
+
logging.warning('No triangles to plot')
|
417
434
|
|
418
435
|
def find_minmax(self,force):
|
419
436
|
""" Find the min and max of the triangulation
|
@@ -1107,9 +1124,9 @@ if :\n \
|
|
1107
1124
|
self.myprops[('Move','Delta Y')] = 0.
|
1108
1125
|
|
1109
1126
|
self.parent.update_lengths()
|
1110
|
-
self.myprops[( 'Geometry','Length 2D')] = self.parent.length2D
|
1111
|
-
self.myprops[( 'Geometry','Length 3D')] = self.parent.length3D
|
1112
|
-
self.myprops[( 'Geometry','Surface')] = self.parent.area
|
1127
|
+
self.myprops[( 'Geometry','Length 2D')] = self.parent.length2D if self.parent.length2D is not None else 0.
|
1128
|
+
self.myprops[( 'Geometry','Length 3D')] = self.parent.length3D if self.parent.length3D is not None else 0.
|
1129
|
+
self.myprops[( 'Geometry','Surface')] = self.parent.area if self.parent.area is not None else 0.
|
1113
1130
|
|
1114
1131
|
self.myprops.Populate()
|
1115
1132
|
class vector:
|
@@ -1748,12 +1765,11 @@ class vector:
|
|
1748
1765
|
prepare(self._polygon)
|
1749
1766
|
|
1750
1767
|
|
1751
|
-
def projectontrace(self, trace):
|
1768
|
+
def projectontrace(self, trace:"vector"):
|
1752
1769
|
"""
|
1753
1770
|
Projection du vecteur sur une trace (type 'vector')
|
1754
1771
|
|
1755
|
-
|
1756
|
-
Nouveau vecteur contenant les infos de position sur la trace et d'altitude (s,z)
|
1772
|
+
:return: Nouveau vecteur contenant les infos de position sur la trace et d'altitude (s,z) aux positions (x,y)
|
1757
1773
|
"""
|
1758
1774
|
|
1759
1775
|
# trace:vector
|
@@ -1770,11 +1786,12 @@ class vector:
|
|
1770
1786
|
|
1771
1787
|
return newvec
|
1772
1788
|
|
1773
|
-
def parallel_offset(self, distance=5., side='left'):
|
1789
|
+
def parallel_offset(self, distance=5., side:Literal['left', 'right']='left'):
|
1774
1790
|
"""
|
1775
|
-
|
1791
|
+
Create a parallel offset of the vector
|
1776
1792
|
|
1777
|
-
The
|
1793
|
+
:param distance: The distance parameter must be a positive float value.
|
1794
|
+
:param side: The side parameter may be ‘left’ or ‘right’. Left and right are determined by following the direction of the given geometric points of the LineString.
|
1778
1795
|
"""
|
1779
1796
|
|
1780
1797
|
if self.nbvertices<2:
|
@@ -1883,6 +1900,9 @@ class vector:
|
|
1883
1900
|
"""
|
1884
1901
|
Ajout de vertices depuis une matrice numpy -- shape = (nb_vert,2 ou 3)
|
1885
1902
|
"""
|
1903
|
+
|
1904
|
+
assert isinstance(xyz, np.ndarray), "xyz must be a numpy array of shape (nb_vert, 2 or 3)"
|
1905
|
+
|
1886
1906
|
if xyz.dtype==np.int32:
|
1887
1907
|
xyz = xyz.astype(np.float64)
|
1888
1908
|
|
@@ -2764,6 +2784,7 @@ class vector:
|
|
2764
2784
|
exit=False
|
2765
2785
|
|
2766
2786
|
if exit:
|
2787
|
+
logging.warning(_('No plotted linked arrays'))
|
2767
2788
|
return
|
2768
2789
|
|
2769
2790
|
k=0
|
@@ -3088,6 +3109,7 @@ class vector:
|
|
3088
3109
|
curvert.x = newx
|
3089
3110
|
|
3090
3111
|
self._reset_listogl()
|
3112
|
+
self.reset_linestring()
|
3091
3113
|
|
3092
3114
|
@y.setter
|
3093
3115
|
def y(self, new_y:np.ndarray | list):
|
@@ -3104,13 +3126,26 @@ class vector:
|
|
3104
3126
|
curvert.y = newy
|
3105
3127
|
|
3106
3128
|
self._reset_listogl()
|
3129
|
+
self.reset_linestring()
|
3107
3130
|
|
3108
3131
|
@z.setter
|
3109
3132
|
def z(self, new_z:np.ndarray | float | list):
|
3110
|
-
""" Set the z values of the vertices
|
3133
|
+
""" Set the z values of the vertices
|
3134
|
+
|
3135
|
+
/PARAM new_z: numpy array, float or list (but WolfArray is supported too)
|
3136
|
+
"""
|
3137
|
+
from .wolf_array import WolfArray
|
3111
3138
|
|
3112
3139
|
if isinstance(new_z, (int, float)):
|
3113
3140
|
new_z = np.full(self.nbvertices, new_z, dtype=float)
|
3141
|
+
elif isinstance(new_z, WolfArray):
|
3142
|
+
wa = new_z
|
3143
|
+
|
3144
|
+
new_z = []
|
3145
|
+
for curvert in self.myvertices:
|
3146
|
+
i,j = wa.xy2ij(curvert.x, curvert.y)
|
3147
|
+
if i>0 and j>0 and i < wa.nbx and j < wa.nby:
|
3148
|
+
new_z.append(wa.array[i, j])
|
3114
3149
|
|
3115
3150
|
if isinstance(new_z, list):
|
3116
3151
|
new_z = np.array(new_z)
|
@@ -3127,6 +3162,7 @@ class vector:
|
|
3127
3162
|
curvert.z = newz
|
3128
3163
|
|
3129
3164
|
self._reset_listogl()
|
3165
|
+
self.reset_linestring()
|
3130
3166
|
|
3131
3167
|
@xyz.setter
|
3132
3168
|
def xyz(self, new_xyz:np.ndarray | list):
|
@@ -3151,6 +3187,8 @@ class vector:
|
|
3151
3187
|
curvert.z = newxyz[2]
|
3152
3188
|
|
3153
3189
|
self._reset_listogl()
|
3190
|
+
self.reset_linestring()
|
3191
|
+
|
3154
3192
|
|
3155
3193
|
@xy.setter
|
3156
3194
|
def xy(self, new_xy:np.ndarray | list):
|
@@ -3168,6 +3206,7 @@ class vector:
|
|
3168
3206
|
curvert.y = newxy[1]
|
3169
3207
|
|
3170
3208
|
self._reset_listogl()
|
3209
|
+
self.reset_linestring()
|
3171
3210
|
|
3172
3211
|
@xz.setter
|
3173
3212
|
def xz(self, new_xz:np.ndarray | list):
|
@@ -3190,6 +3229,7 @@ class vector:
|
|
3190
3229
|
curvert.z = newxz[1]
|
3191
3230
|
|
3192
3231
|
self._reset_listogl()
|
3232
|
+
self.reset_linestring()
|
3193
3233
|
|
3194
3234
|
@xyzi.setter
|
3195
3235
|
def xyzi(self, new_xyzi:np.ndarray | list):
|
@@ -3209,6 +3249,7 @@ class vector:
|
|
3209
3249
|
curvert.in_use = newxyzi[3]
|
3210
3250
|
|
3211
3251
|
self._reset_listogl()
|
3252
|
+
self.reset_linestring()
|
3212
3253
|
|
3213
3254
|
@xyi.setter
|
3214
3255
|
def xyi(self, new_xyi:np.ndarray | list):
|
@@ -3227,6 +3268,7 @@ class vector:
|
|
3227
3268
|
curvert.in_use = newxyi[2]
|
3228
3269
|
|
3229
3270
|
self._reset_listogl()
|
3271
|
+
self.reset_linestring()
|
3230
3272
|
|
3231
3273
|
@i.setter
|
3232
3274
|
def i(self, new_i:np.ndarray | list):
|
@@ -3243,6 +3285,23 @@ class vector:
|
|
3243
3285
|
curvert.in_use = newi
|
3244
3286
|
|
3245
3287
|
self._reset_listogl()
|
3288
|
+
self.reset_linestring()
|
3289
|
+
|
3290
|
+
@sz_curvi.setter
|
3291
|
+
def sz_curvi(self, sz_new:np.ndarray | list):
|
3292
|
+
""" Interpolate the vertices based on the curvilinear abscissa """
|
3293
|
+
|
3294
|
+
if isinstance(sz_new, list):
|
3295
|
+
sz_new = np.array(sz_new)
|
3296
|
+
|
3297
|
+
f = interp1d(sz_new[:,0],sz_new[:,1], bounds_error=False, fill_value='extrapolate')
|
3298
|
+
|
3299
|
+
s = self.s_curvi
|
3300
|
+
for idx, curvert in enumerate(self.myvertices):
|
3301
|
+
curvert.z = f(s[idx])
|
3302
|
+
|
3303
|
+
self._reset_listogl()
|
3304
|
+
self.reset_linestring()
|
3246
3305
|
|
3247
3306
|
def __str__(self):
|
3248
3307
|
return self.myname
|
@@ -3265,6 +3324,7 @@ class vector:
|
|
3265
3324
|
if ndx>=0 and ndx < self.nbvertices:
|
3266
3325
|
self.myvertices[ndx] = value
|
3267
3326
|
self._reset_listogl()
|
3327
|
+
self.reset_linestring()
|
3268
3328
|
else:
|
3269
3329
|
logging.warning(_('Index out of range'))
|
3270
3330
|
|
@@ -3273,6 +3333,7 @@ class vector:
|
|
3273
3333
|
if ndx>=0 and ndx < self.nbvertices:
|
3274
3334
|
self.myvertices.pop(ndx)
|
3275
3335
|
self._reset_listogl()
|
3336
|
+
self.reset_linestring()
|
3276
3337
|
else:
|
3277
3338
|
logging.warning(_('Index out of range'))
|
3278
3339
|
|
@@ -3290,6 +3351,7 @@ class vector:
|
|
3290
3351
|
|
3291
3352
|
self.update_lengths()
|
3292
3353
|
self._reset_listogl()
|
3354
|
+
self.reset_linestring()
|
3293
3355
|
|
3294
3356
|
def cut(self, s:float, is3D:bool=True, adim:bool=True, frombegin:bool=True):
|
3295
3357
|
"""
|
@@ -3312,6 +3374,7 @@ class vector:
|
|
3312
3374
|
newvec.update_lengths()
|
3313
3375
|
|
3314
3376
|
self._reset_listogl()
|
3377
|
+
self.reset_linestring()
|
3315
3378
|
|
3316
3379
|
return newvec
|
3317
3380
|
|
@@ -6333,7 +6396,7 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6333
6396
|
"""
|
6334
6397
|
Retourne la zone sur base de son nom ou de sa position
|
6335
6398
|
|
6336
|
-
:param ndx: Clé ou index de zone -- si tuple, alors (idx_zone, idx_vect)
|
6399
|
+
:param ndx: Clé ou index de zone -- si tuple, alors (idx_zone, idx_vect) ou (keyzone, keyvect)
|
6337
6400
|
|
6338
6401
|
"""
|
6339
6402
|
|
@@ -6698,16 +6761,26 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6698
6761
|
self.xls.CreateGrid(10,6)
|
6699
6762
|
|
6700
6763
|
sizer_add_update = BoxSizer(orient=wx.HORIZONTAL)
|
6701
|
-
self.addrows = wx.Button(self,label=_('
|
6764
|
+
self.addrows = wx.Button(self,label=_('Rows+'))
|
6702
6765
|
self.addrows.SetToolTip(_("Add rows to the grid --> Useful for manually adding some points to a vector"))
|
6703
6766
|
self.addrows.Bind(wx.EVT_BUTTON,self.Onaddrows)
|
6704
6767
|
|
6705
|
-
self.updatevertices = wx.Button(self,label=_('Update
|
6768
|
+
self.updatevertices = wx.Button(self,label=_('Update'))
|
6706
6769
|
self.updatevertices.SetToolTip(_("Transfer the coordinates from the editor to the memory and update the plot"))
|
6707
6770
|
self.updatevertices.Bind(wx.EVT_BUTTON,self.Onupdatevertices)
|
6708
6771
|
|
6772
|
+
self.plot_mpl = wx.Button(self,label=_('Plot xy'))
|
6773
|
+
self.plot_mpl.SetToolTip(_("Plot the active vector in a new window (matplotlib)"))
|
6774
|
+
self.plot_mpl.Bind(wx.EVT_BUTTON,self.Onplotmpl)
|
6775
|
+
|
6776
|
+
self.plot_mplsz = wx.Button(self,label=_('Plot sz'))
|
6777
|
+
self.plot_mplsz.SetToolTip(_("Plot the active vector in a new window (matplotlib)"))
|
6778
|
+
self.plot_mplsz.Bind(wx.EVT_BUTTON,self.Onplotmplsz)
|
6779
|
+
|
6709
6780
|
sizer_add_update.Add(self.addrows,1, wx.EXPAND)
|
6710
6781
|
sizer_add_update.Add(self.updatevertices,3, wx.EXPAND)
|
6782
|
+
sizer_add_update.Add(self.plot_mpl,1, wx.EXPAND)
|
6783
|
+
sizer_add_update.Add(self.plot_mplsz,1, wx.EXPAND)
|
6711
6784
|
|
6712
6785
|
self.capturevertices = wx.Button(self,label=_('Add'))
|
6713
6786
|
self.capturevertices.SetToolTip(_("Capture new points from mouse clicks \n\n Keyboard 'Return' to stop the action ! "))
|
@@ -6725,6 +6798,10 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6725
6798
|
self.createapar.SetToolTip(_("Create a single parallel to the currently activated vector as a new vector in the same zone"))
|
6726
6799
|
self.createapar.Bind(wx.EVT_BUTTON,self.OnAddPar)
|
6727
6800
|
|
6801
|
+
self._btn_simplify = wx.Button(self,label=_('Simplify'))
|
6802
|
+
self._btn_simplify.SetToolTip(_("Simplify the currently activated vector using the Douglas-Peucker algorithm"))
|
6803
|
+
self._btn_simplify.Bind(wx.EVT_BUTTON,self.Onsimplify)
|
6804
|
+
|
6728
6805
|
sizer_reverse_split = BoxSizer(orient=wx.HORIZONTAL)
|
6729
6806
|
self.reverseorder = wx.Button(self,label=_('Reverse points order'))
|
6730
6807
|
self.reverseorder.SetToolTip(_("Reverse the order/sens of the currently activated vector -- Overwrite the data"))
|
@@ -6734,6 +6811,10 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6734
6811
|
self.sascending.SetToolTip(_("Check whether the vertices of the activated vector are ordered according to increasing 's' defined as 2D geometric distance \n If needed, invert some positions and return information to the user"))
|
6735
6812
|
self.sascending.Bind(wx.EVT_BUTTON,self.Onsascending)
|
6736
6813
|
|
6814
|
+
self._btn_buffer = wx.Button(self,label=_('Buffer'))
|
6815
|
+
self._btn_buffer.SetToolTip(_("Create a buffer around the currently activated vector\nThe buffer replaces the current vector"))
|
6816
|
+
self._btn_buffer.Bind(wx.EVT_BUTTON,self.Onbuffer)
|
6817
|
+
|
6737
6818
|
self.insertvertices = wx.Button(self,label=_('Insert'))
|
6738
6819
|
self.insertvertices.SetToolTip(_("Insert new vertex into the currently active vector from mouse clicks \n The new vertex is inserted along the nearest segment \n\n Keyboard 'Return' to stop the action ! "))
|
6739
6820
|
self.insertvertices.Bind(wx.EVT_BUTTON,self.Oninsert)
|
@@ -6830,7 +6911,11 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6830
6911
|
subboxmod.Add(self.insertvertices,1,wx.EXPAND)
|
6831
6912
|
boxright.Add(subboxmod,0,wx.EXPAND)
|
6832
6913
|
|
6833
|
-
|
6914
|
+
subboxparsimpl = wx.BoxSizer(orient=wx.HORIZONTAL)
|
6915
|
+
subboxparsimpl.Add(self.createapar,1,wx.EXPAND)
|
6916
|
+
subboxparsimpl.Add(self._btn_simplify,1,wx.EXPAND)
|
6917
|
+
|
6918
|
+
boxright.Add(subboxparsimpl,0,wx.EXPAND)
|
6834
6919
|
|
6835
6920
|
sizer_reverse_split.Add(self.reverseorder,1,wx.EXPAND)
|
6836
6921
|
sizer_reverse_split.Add(self.splitvertices,1,wx.EXPAND)
|
@@ -6848,8 +6933,11 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
6848
6933
|
box_s.Add(self.getxyfromsz,1,wx.EXPAND) # Added
|
6849
6934
|
|
6850
6935
|
boxright.Add(self.interpxyz,0,wx.EXPAND)
|
6851
|
-
boxright.Add(self.sascending,0,wx.EXPAND)
|
6852
6936
|
|
6937
|
+
_sizer_ascbuffer = wx.BoxSizer(wx.HORIZONTAL)
|
6938
|
+
_sizer_ascbuffer.Add(self.sascending,1,wx.EXPAND)
|
6939
|
+
_sizer_ascbuffer.Add(self._btn_buffer,1,wx.EXPAND)
|
6940
|
+
boxright.Add(_sizer_ascbuffer,0,wx.EXPAND)
|
6853
6941
|
|
6854
6942
|
sizer_values_surface = wx.BoxSizer(wx.HORIZONTAL)
|
6855
6943
|
self.butgetval = wx.Button(self,label=_('Get values'))
|
@@ -7256,6 +7344,46 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
7256
7344
|
self.fill_structure()
|
7257
7345
|
self.active_vector._reset_listogl()
|
7258
7346
|
|
7347
|
+
def Onsimplify(self, event:wx.MouseEvent):
|
7348
|
+
"""
|
7349
|
+
Simplify the active vector using the Douglas-Peucker algorithm
|
7350
|
+
"""
|
7351
|
+
|
7352
|
+
if self.verify_activevec():
|
7353
|
+
return
|
7354
|
+
|
7355
|
+
tolerance = 1.0
|
7356
|
+
if self.wx_exists:
|
7357
|
+
|
7358
|
+
dlg = wx.TextEntryDialog(None, _('Tolerance ?'), value='1.0')
|
7359
|
+
ret = dlg.ShowModal()
|
7360
|
+
tolerance = dlg.GetValue()
|
7361
|
+
dlg.Destroy()
|
7362
|
+
try:
|
7363
|
+
tolerance = float(tolerance)
|
7364
|
+
except:
|
7365
|
+
logging.warning(_('Bad value -- Retry !'))
|
7366
|
+
return
|
7367
|
+
|
7368
|
+
new_ls = self.active_vector.linestring.simplify(tolerance, preserve_topology=True)
|
7369
|
+
|
7370
|
+
xy = new_ls.xy # shape (2, n)
|
7371
|
+
xy = np.array(xy).T # shape (n, 2)
|
7372
|
+
|
7373
|
+
if len(xy) == 0:
|
7374
|
+
logging.warning(_('No points to add'))
|
7375
|
+
return
|
7376
|
+
|
7377
|
+
tmp = self.active_vector.deepcopy().linestring
|
7378
|
+
self.active_vector.reset()
|
7379
|
+
for x, y in xy:
|
7380
|
+
pt = Point(x, y)
|
7381
|
+
self.active_vector.add_vertex(wolfvertex(x, y, tmp.interpolate(tmp.project(pt)).z))
|
7382
|
+
|
7383
|
+
self.xls_active_vector()
|
7384
|
+
self.active_vector._reset_listogl()
|
7385
|
+
|
7386
|
+
|
7259
7387
|
def OnAddPar(self, event:wx.MouseEvent):
|
7260
7388
|
"""
|
7261
7389
|
Ajout d'une parallèle au vecteur courant via le bouton adhoc
|
@@ -7370,6 +7498,37 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
7370
7498
|
dlg.ShowModal()
|
7371
7499
|
dlg.Destroy()
|
7372
7500
|
|
7501
|
+
def Onbuffer(self, e:wx.MouseEvent):
|
7502
|
+
""" Create a buffer around the currently activated vector.
|
7503
|
+
The buffer replaces the active vector in the same zone."""
|
7504
|
+
|
7505
|
+
if self.wx_exists:
|
7506
|
+
if self.verify_activevec():
|
7507
|
+
return
|
7508
|
+
|
7509
|
+
dlg = wx.TextEntryDialog(None, _('Buffer distance ?'), value='5.0')
|
7510
|
+
ret = dlg.ShowModal()
|
7511
|
+
dist = dlg.GetValue()
|
7512
|
+
dlg.Destroy()
|
7513
|
+
try:
|
7514
|
+
dist = float(dist)
|
7515
|
+
except:
|
7516
|
+
logging.warning(_('Bad value -- Retry !'))
|
7517
|
+
return
|
7518
|
+
if dist <= 0:
|
7519
|
+
logging.warning(_('Buffer distance must be > 0 -- Retry !'))
|
7520
|
+
return
|
7521
|
+
|
7522
|
+
if self.active_vector.nbvertices == 1:
|
7523
|
+
self.active_vector.myvertices = self.active_vector.myvertices * 3
|
7524
|
+
logging.warning(_('The active vector has only one vertex. It will be duplicated to create a buffer.'))
|
7525
|
+
if self.active_vector.nbvertices == 2:
|
7526
|
+
self.active_vector.myvertices = self.active_vector.myvertices + [self.active_vector.myvertices[0]]
|
7527
|
+
logging.warning(_('The active vector has only two vertices. The first one will be duplicated to create a buffer.'))
|
7528
|
+
|
7529
|
+
self.active_vector.buffer(dist)
|
7530
|
+
self.active_vector._reset_listogl()
|
7531
|
+
|
7373
7532
|
def Onmodify(self, event:wx.MouseEvent):
|
7374
7533
|
"""
|
7375
7534
|
Permet la modification interactive de vertex dans le vector actif
|
@@ -7941,6 +8100,9 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
7941
8100
|
# Getting s values and Z values from the xls grid
|
7942
8101
|
# s in column 4 and z in column 2
|
7943
8102
|
# The first row is the header
|
8103
|
+
nbrows = self.xls.GetNumberRows()
|
8104
|
+
if self.xls.GetCellValue(nbrows-1,4) != '':
|
8105
|
+
self.xls.AppendRows(1)
|
7944
8106
|
i = 0
|
7945
8107
|
while self.xls.GetCellValue(i,4) != '':
|
7946
8108
|
s = self.xls.GetCellValue(i,4)
|
@@ -8024,7 +8186,21 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
8024
8186
|
|
8025
8187
|
self.find_minmax(True)
|
8026
8188
|
|
8027
|
-
def update_from_sz_support(self,
|
8189
|
+
def update_from_sz_support(self,
|
8190
|
+
vec: vector,
|
8191
|
+
sz:np.ndarray,
|
8192
|
+
dialog_box = True,
|
8193
|
+
method:Literal['2D', '3D'] = '3D'):
|
8194
|
+
""" Update the coordinates from the support vector and a sz array.
|
8195
|
+
|
8196
|
+
The support vector is used to interpolate the z values, at the s values.
|
8197
|
+
It must long enough to cover the s values.
|
8198
|
+
|
8199
|
+
:param vec: The vector to update. It is also the support vector.
|
8200
|
+
:param sz: The sz array to use for the update
|
8201
|
+
:param dialog_box: If True, a dialog box will be shown to choose the method
|
8202
|
+
:param method: The method to use for the interpolation. '2D' or '3D'
|
8203
|
+
"""
|
8028
8204
|
|
8029
8205
|
if sz.shape[0] ==0:
|
8030
8206
|
logging.warning(_('No data to update'))
|
@@ -8046,8 +8222,12 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
8046
8222
|
|
8047
8223
|
method=dlg.GetStringSelection()
|
8048
8224
|
dlg.Destroy()
|
8049
|
-
else:
|
8050
|
-
|
8225
|
+
# else:
|
8226
|
+
# method = '2D'
|
8227
|
+
|
8228
|
+
if method not in ['2D', '3D']:
|
8229
|
+
logging.warning(_('Method not supported -- only 2D and 3D are supported'))
|
8230
|
+
return
|
8051
8231
|
|
8052
8232
|
if method == '2D':
|
8053
8233
|
if sz[-1,0] > support_vec.length2D:
|
@@ -8060,18 +8240,21 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
8060
8240
|
|
8061
8241
|
vec.myvertices = []
|
8062
8242
|
for s,z in sz:
|
8063
|
-
new_vertex = support_vec.interpolate(s, method ==
|
8243
|
+
new_vertex = support_vec.interpolate(s, method == method, adim= False)
|
8064
8244
|
new_vertex.z = z
|
8065
8245
|
vec.add_vertex(new_vertex)
|
8066
8246
|
|
8247
|
+
vec._reset_listogl()
|
8248
|
+
vec.update_lengths()
|
8249
|
+
|
8067
8250
|
self.find_minmax(True)
|
8068
8251
|
|
8069
|
-
def evaluate_s
|
8252
|
+
def evaluate_s(self, vec: vector =None, dialog_box = True):
|
8070
8253
|
"""
|
8071
|
-
Calcule la position curviligne du vecteur
|
8254
|
+
Calcule la position curviligne du vecteur encodé.
|
8072
8255
|
|
8073
|
-
Le calcul peut être mené en 2D ou en 3D
|
8074
|
-
Remplissage du tableur dans la 5ème colonne
|
8256
|
+
Le calcul peut être mené en 2D ou en 3D.
|
8257
|
+
Remplissage du tableur dans la 5ème colonne.
|
8075
8258
|
"""
|
8076
8259
|
|
8077
8260
|
curv = vec
|
@@ -8143,6 +8326,33 @@ class Zones(wx.Frame, Element_To_Draw):
|
|
8143
8326
|
self.active_vector.updatefromgrid(self.xls)
|
8144
8327
|
self.find_minmax(True)
|
8145
8328
|
|
8329
|
+
def Onplotmpl(self, event:wx.MouseEvent):
|
8330
|
+
"""
|
8331
|
+
Plot active vector in matplotlib
|
8332
|
+
"""
|
8333
|
+
|
8334
|
+
if self.verify_activevec():
|
8335
|
+
return
|
8336
|
+
|
8337
|
+
fig, ax = plt.subplots()
|
8338
|
+
self.active_vector.plot_matplotlib(ax)
|
8339
|
+
ax.set_aspect('equal')
|
8340
|
+
fig.show()
|
8341
|
+
|
8342
|
+
def Onplotmplsz(self, event:wx.MouseEvent):
|
8343
|
+
"""
|
8344
|
+
Plot active vector in matplotlib with sz values
|
8345
|
+
"""
|
8346
|
+
if self.verify_activevec():
|
8347
|
+
return
|
8348
|
+
|
8349
|
+
fig, ax = plt.subplots()
|
8350
|
+
s, z = self.active_vector.sz_curvi
|
8351
|
+
ax.plot(s, z)
|
8352
|
+
ax.set_xlabel('s')
|
8353
|
+
ax.set_ylabel('z')
|
8354
|
+
fig.show()
|
8355
|
+
|
8146
8356
|
def Onaddrows(self, event:wx.MouseEvent):
|
8147
8357
|
"""
|
8148
8358
|
Ajout de lignes au tableur
|