wolfhece 2.1.117__py3-none-any.whl → 2.1.118__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 CHANGED
@@ -84,7 +84,7 @@ try:
84
84
  from .Results2DGPU import wolfres2DGPU
85
85
  from .PyCrosssections import crosssections, profile, Interpolator, Interpolators
86
86
  from .GraphNotebook import PlotNotebook
87
- from .lazviewer.laz_viewer import myviewer, read_laz, clip_data_xyz, xyz_laz_grids, choices_laz_colormap, Classification_LAZ
87
+ from .lazviewer.laz_viewer import myviewer, read_laz, clip_data_xyz, xyz_laz_grids, choices_laz_colormap, Classification_LAZ, Base_LAZ_Data, viewer as viewerlaz
88
88
  from . import Lidar2002
89
89
  from .picc import Picc_data, Cadaster_data
90
90
  from .wolf_zi_db import ZI_Databse_Elt, PlansTerrier
@@ -557,6 +557,7 @@ class draw_type(Enum):
557
557
  WMSFORE = 'wms-foreground'
558
558
  TILES = 'tiles'
559
559
  IMAGESTILES = 'imagestiles'
560
+ LAZ = 'laz'
560
561
 
561
562
  class Colors_1to9(wx.Frame):
562
563
 
@@ -1171,6 +1172,8 @@ class WolfMapViewer(wx.Frame):
1171
1172
  myimagestiles: list[ImagesTiles]
1172
1173
  mypartsystems: list[Particle_system]
1173
1174
  myviewers3d:list[Wolf_Viewer3D]
1175
+ mylazdata:list[Base_LAZ_Data]
1176
+
1174
1177
  sim_explorers: dict[Wolfresults_2D:Sim_Explorer]
1175
1178
 
1176
1179
  canvas: GLCanvas # canvas OpenGL
@@ -1196,10 +1199,12 @@ class WolfMapViewer(wx.Frame):
1196
1199
  active_imagestiles: ImagesTiles
1197
1200
  active_particle_system: Particle_system
1198
1201
  active_viewer3d: Wolf_Viewer3D
1202
+ active_viewerlaz: viewerlaz
1199
1203
  active_bridges: Bridges
1200
1204
  active_bridge: Bridge
1201
1205
  active_weirs : Weirs
1202
1206
  active_weir : Weir
1207
+ active_laz : Base_LAZ_Data
1203
1208
 
1204
1209
  def __init__(self,
1205
1210
  wxparent = None,
@@ -1275,9 +1280,7 @@ class WolfMapViewer(wx.Frame):
1275
1280
  self.forcemimic = True
1276
1281
  self.currently_readresults = False
1277
1282
 
1278
- self.mylazdata = None
1279
- # self.mylazdata_colors = None
1280
- self.mylazgrid = None
1283
+ self.mylazgrid:xyz_laz_grids = None # LAZ grid preprocessed by Numpy
1281
1284
 
1282
1285
  self.colors1to9 = Colors_1to9(self)
1283
1286
 
@@ -1309,7 +1312,7 @@ class WolfMapViewer(wx.Frame):
1309
1312
  self.menuimagestiles = None
1310
1313
 
1311
1314
  self.filemenu = wx.Menu()
1312
- openitem = self.filemenu.Append(wx.ID_OPEN, _('Open/Add project'), _('Open a complete project from file'))
1315
+ openitem = self.filemenu.Append(wx.ID_OPEN, _('Open/Add project'), _('Open a full project from file'))
1313
1316
  saveproject = self.filemenu.Append(wx.ID_ANY, _('Save project as...'), _('Save the current project to file'))
1314
1317
  self.filemenu.AppendSeparator()
1315
1318
  saveitem = self.filemenu.Append(wx.ID_SAVE, _('Save'), _('Save all checked arrays or vectors to files'))
@@ -1535,6 +1538,7 @@ class WolfMapViewer(wx.Frame):
1535
1538
  self.active_res2d = None
1536
1539
  self.active_particle_system = None
1537
1540
  self.active_viewer3d = None
1541
+ self.active_viewerlaz = None
1538
1542
  self.active_landmap:PlansTerrier = None
1539
1543
  self.active_tile = None
1540
1544
  self.selected_treeitem = None
@@ -1543,6 +1547,7 @@ class WolfMapViewer(wx.Frame):
1543
1547
  self.active_bridge = None
1544
1548
  self.active_weirs = None
1545
1549
  self.active_weir = None
1550
+ self.active_laz = None
1546
1551
 
1547
1552
  curtool = self.tools[ID_SORTALONG] = {}
1548
1553
  curtool['menu'] = self.sortalong
@@ -1591,14 +1596,15 @@ class WolfMapViewer(wx.Frame):
1591
1596
 
1592
1597
  self.root = self.treelist.GetRootItem()
1593
1598
  self.treelist.AppendColumn(_('Objects to plot'))
1594
- self.myitemsarray = self.treelist.AppendItem(self.root, _("Arrays"))
1599
+ self.myitemsarray = self.treelist.AppendItem(self.root, _("Arrays"))
1595
1600
  self.myitemsvector = self.treelist.AppendItem(self.root, _("Vectors"))
1596
- self.myitemscloud = self.treelist.AppendItem(self.root, _("Clouds"))
1597
- self.myitemstri = self.treelist.AppendItem(self.root, _("Triangulations"))
1598
- self.myitemsres2d = self.treelist.AppendItem(self.root, _("Wolf2D"))
1599
- self.myitemsps = self.treelist.AppendItem(self.root, _("Particle systems"))
1601
+ self.myitemscloud = self.treelist.AppendItem(self.root, _("Clouds"))
1602
+ self.myitemslaz = self.treelist.AppendItem(self.root, _("Laz"))
1603
+ self.myitemstri = self.treelist.AppendItem(self.root, _("Triangulations"))
1604
+ self.myitemsres2d = self.treelist.AppendItem(self.root, _("Wolf2D"))
1605
+ self.myitemsps = self.treelist.AppendItem(self.root, _("Particle systems"))
1600
1606
  self.myitemsothers = self.treelist.AppendItem(self.root, _("Others"))
1601
- self.myitemsviews = self.treelist.AppendItem(self.root, _("Views"))
1607
+ self.myitemsviews = self.treelist.AppendItem(self.root, _("Views"))
1602
1608
  self.myitemswmsback = self.treelist.AppendItem(self.root, _("WMS-background"))
1603
1609
  self.myitemswmsfore = self.treelist.AppendItem(self.root, _("WMS-foreground"))
1604
1610
 
@@ -1922,17 +1928,20 @@ class WolfMapViewer(wx.Frame):
1922
1928
  self.menulaz.AppendSubMenu(self.menulazdata, _('LAZ data'))
1923
1929
  self.menulaz.AppendSubMenu(self.menulazgrid, _('LAZ grid'))
1924
1930
 
1925
- readlaz = self.menulazdata.Append(wx.ID_ANY, _('Initialize from npz'), _('LAZ from Numpy array'))
1926
- readlaz_gridinfo = self.menulazgrid.Append(wx.ID_ANY, _('Initialize from GridInfos'), _('LAZ from gridinfos - subgridding of LAZ files'), kind=wx.ITEM_CHECK)
1931
+ readlaz = self.menulazdata.Append(wx.ID_ANY, _('Initialize from laz, las or npz'), _('LAZ data from one specific file (type laz, las or npz)'))
1932
+ readlaz_gridinfo = self.menulazgrid.Append(wx.ID_ANY, _('Initialize from directory'), _('LAZ GRID stored in a directory - subgridding of LAZ files'), kind=wx.ITEM_CHECK)
1933
+ updatecolors_laz = self.menulazgrid.Append(wx.ID_ANY, _('Change colors - Classification'), _('Change color map associated to the current classification'),)
1927
1934
 
1928
- bridgelaz = self.menulazdata.Append(wx.ID_ANY, _('Create cloud points from bridges'), _('LAZ Bridge'))
1929
- buildinglaz = self.menulazdata.Append(wx.ID_ANY, _('Create cloud points from buildings'), _('LAZ Buildings'))
1935
+ bridgelaz = self.menulazdata.Append(wx.ID_ANY, _('Create cloud points from bridges'), _('Extract bridge from LAZ data as cloud points (class 10)'))
1936
+ buildinglaz = self.menulazdata.Append(wx.ID_ANY, _('Create cloud points from buildings'), _('Extract buildings from LAZ data as cloud points (class 1)'))
1937
+ classlaz = self.menulazdata.Append(wx.ID_ANY, _('Create cloud points from specified classes'), _('Extract cloud points from LAZ data (class to specify)'))
1930
1938
 
1931
1939
  croplaz = self.menulaz.Append(wx.ID_ANY, _('Clip LAZ grid on current zoom'), _('Select LAZ data based on the visible screen extent'),)
1932
1940
  viewlaz = self.menulaz.Append(wx.ID_ANY, _('Create LAZ viewer'), _('Create a LAZ Viewer based on loaded data'))
1941
+ filterlaz = self.menulaz.Append(wx.ID_ANY, _('Filter data based on codes'), _('Filter LAZ data based on codes'),)
1942
+ descimate_laz = self.menulaz.Append(wx.ID_ANY, _('Descimate LAZ data'), _('Descimate LAZ data'),)
1933
1943
  aroundlaz = self.menulaz.Append(wx.ID_ANY, _('Plot LAZ around active vector'), _('Display a Matplotlib plot with the LAZ values around the active vector/polyline'),)
1934
1944
  pick_aroundlaz = self.menulaz.Append(wx.ID_ANY, _('Plot LAZ around temporary vector'), _('Display a Matplotlib plot with the LAZ values around a temporary vector/polyline -- Right clicks to add points + Enter'),)
1935
- updatecolors_laz = self.menulaz.Append(wx.ID_ANY, _('Change colors - Classification'), _('Change color map associated to the current classification'),)
1936
1945
  fillarray_laz = self.menulaz.Append(wx.ID_ANY, _('Fill active array from LAZ data'), _('Fill an array from the LAZ data'),)
1937
1946
  selectarray_laz = self.menulaz.Append(wx.ID_ANY, _('Select cells in array from LAZ data'), _('Select nodes in active array from the LAZ data'),)
1938
1947
  countarray_laz = self.menulaz.Append(wx.ID_ANY, _('Count LAZ data in cells'), _('Count the number of LAZ data in each cell of the matrix'),)
@@ -3890,10 +3899,13 @@ class WolfMapViewer(wx.Frame):
3890
3899
  self.mywmsfore = []
3891
3900
  self.myres2D = []
3892
3901
  self.myviewers3d = []
3902
+ self.myviewerslaz = []
3903
+ self.mylazdata = []
3904
+
3893
3905
  self.sim_explorers = {}
3894
3906
 
3895
3907
  # liste des éléments modifiable dans l'arbre
3896
- self.all_lists = [self.myarrays, self.myvectors, self.myclouds, self.mytri, self.myothers, self.myviews, self.myres2D, self.mytiles, self.myimagestiles, self.mypartsystems, self.myviewers3d]
3908
+ self.all_lists = [self.myarrays, self.myvectors, self.myclouds, self.mytri, self.myothers, self.myviews, self.myres2D, self.mytiles, self.myimagestiles, self.mypartsystems, self.myviewers3d, self.myviewerslaz]
3897
3909
 
3898
3910
  self.menu_options = wx.Menu()
3899
3911
  self._change_title = self.menu_options.Append(wx.ID_ANY, _('Change title'), _('Change title of the window'))
@@ -5524,22 +5536,66 @@ class WolfMapViewer(wx.Frame):
5524
5536
  """ Clip laz grid on current zoom """
5525
5537
 
5526
5538
  if self.mylazgrid is None:
5539
+ logging.warning(_('No laz grid -- Please initialize it !'))
5527
5540
  return
5528
5541
 
5529
5542
  curbounds = [[self.xmin, self.xmin + self.width], [self.ymin, self.ymin + self.height]]
5530
5543
 
5531
- self.mylazdata = self.mylazgrid.scan(curbounds)
5544
+ if self.active_laz is None:
5545
+ newobj = Base_LAZ_Data()
5546
+ newobj.classification = self.mylazgrid.colors
5547
+ newobj.from_grid(self.mylazgrid, curbounds)
5548
+
5549
+ self.add_object('laz', newobj= newobj)
5550
+
5551
+ else:
5552
+ dlg = wx.MessageDialog(None, _('Do you want to keep the current data ?'), _('Keep data ?'), wx.YES_NO | wx.ICON_QUESTION)
5553
+ ret = dlg.ShowModal()
5554
+
5555
+ if ret == wx.ID_YES:
5556
+ newobj = Base_LAZ_Data()
5557
+ newobj.classification = self.mylazgrid.colors
5558
+ newobj.from_grid(self.mylazgrid, curbounds)
5532
5559
 
5533
- logging.info(_('Clip LAZ grid on current zoom {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5560
+ self.add_object('laz', newobj= newobj)
5561
+
5562
+ else:
5563
+
5564
+ self.active_laz.from_grid(self.mylazgrid, curbounds)
5565
+
5566
+ logging.info(_('Clip LAZ grid on current zoom'))
5567
+ logging.info(_('Bounds {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5568
+ logging.info(_('Nb points : {}').format(self.active_laz.num_points))
5569
+
5570
+ def filter_active_laz(self):
5571
+ """ Filter active laz data """
5572
+
5573
+ if self.active_laz is None:
5574
+ logging.warning(_('No laz data'))
5575
+ return
5576
+
5577
+ codes = self.active_laz.codes_unique()
5578
+
5579
+ names = [self.active_laz.classification.classification[curcode][0] for curcode in codes]
5580
+
5581
+ with wx.MultiChoiceDialog(None, _('Choose the codes to keep'), _('Codes'), names) as dlg:
5582
+ if dlg.ShowModal() == wx.ID_OK:
5583
+ used_codes = dlg.GetSelections()
5584
+ used_codes = [codes[cur] for cur in used_codes]
5585
+ self.active_laz.filter_data(used_codes)
5586
+
5587
+ logging.info(_('Filter done - Nb points : {}').format(self.active_laz.num_points))
5588
+ else:
5589
+ logging.info(_('Filter cancelled'))
5534
5590
 
5535
5591
  def decimate_laz_data(self, factor:int = 10):
5536
5592
  """ Decimate data """
5537
5593
 
5538
- if self.mylazdata is None:
5594
+ if self.active_laz is None:
5539
5595
  logging.warning(_('No laz data'))
5540
5596
  return
5541
5597
 
5542
- self.mylazdata = self.mylazdata[::factor]
5598
+ self.active_laz.decimate(factor)
5543
5599
 
5544
5600
  def select_active_array_from_laz(self, array:WolfArray = None, used_codes:list = None, chunk_size:float = 500.):
5545
5601
  """ select some nodes from laz data
@@ -5548,6 +5604,7 @@ class WolfMapViewer(wx.Frame):
5548
5604
  :param used_codes: codes to use
5549
5605
  """
5550
5606
  if self.mylazgrid is None:
5607
+ logging.info(_('No laz grid - Aborting !'))
5551
5608
  return
5552
5609
 
5553
5610
  if array is None:
@@ -5581,19 +5638,19 @@ class WolfMapViewer(wx.Frame):
5581
5638
  curbounds = [[curx, curx + chunk_size], [cury, cury + chunk_size]]
5582
5639
 
5583
5640
  logging.info(_('Scan {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5584
- self.mylazdata = self.mylazgrid.scan(curbounds)
5641
+ mylazdata = self.mylazgrid.scan(curbounds)
5585
5642
  # logging.info(_('Scan done'))
5586
5643
 
5587
5644
  data = {}
5588
5645
  for curcode in used_codes:
5589
- data[curcode] = self.mylazdata[self.mylazdata[:, 3] == curcode]
5646
+ data[curcode] = mylazdata[mylazdata[:, 3] == curcode]
5590
5647
 
5591
5648
  for curdata in data.values():
5592
5649
 
5593
5650
  if curdata.shape[0] == 0:
5594
5651
  continue
5595
5652
 
5596
- i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1]) #= np.float32(self.mylazdata[:, 2])
5653
+ i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1])
5597
5654
 
5598
5655
  keys = np.vstack((i,j)).T
5599
5656
 
@@ -5616,6 +5673,7 @@ class WolfMapViewer(wx.Frame):
5616
5673
  """
5617
5674
 
5618
5675
  if self.mylazgrid is None:
5676
+ logging.info(_('No laz grid - Aborting !'))
5619
5677
  return
5620
5678
 
5621
5679
  if array is None:
@@ -5679,16 +5737,16 @@ class WolfMapViewer(wx.Frame):
5679
5737
  curbounds = [[curx, curx + chunk_size], [cury, cury + chunk_size]]
5680
5738
 
5681
5739
  logging.info(_('Scan {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5682
- self.mylazdata = self.mylazgrid.scan(curbounds)
5740
+ mylazdata = self.mylazgrid.scan(curbounds)
5683
5741
  # logging.info(_('Scan done'))
5684
5742
 
5685
- if len(self.mylazdata) == 0:
5743
+ if len(mylazdata) == 0:
5686
5744
  continue
5687
5745
 
5688
5746
  # Test codes
5689
5747
  data = {}
5690
5748
  for curcode in used_codes:
5691
- data[curcode] = self.mylazdata[self.mylazdata[:, 3] == curcode]
5749
+ data[curcode] = mylazdata[mylazdata[:, 3] == curcode]
5692
5750
 
5693
5751
  # Treat data for each code
5694
5752
  for curdata in data.values():
@@ -5699,7 +5757,7 @@ class WolfMapViewer(wx.Frame):
5699
5757
  logging.info(_('Code {} : {} points'.format(curdata[0,3], curdata.shape[0])))
5700
5758
 
5701
5759
  # get i,j from x,y
5702
- i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1]) #= np.float32(self.mylazdata[:, 2])
5760
+ i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1])
5703
5761
 
5704
5762
  # keep only valid points -- inside the array
5705
5763
  used = np.where((i >=0) & (i < array.nbx) & (j >=0) & (j < array.nby))[0]
@@ -5766,6 +5824,7 @@ class WolfMapViewer(wx.Frame):
5766
5824
  """
5767
5825
 
5768
5826
  if self.mylazgrid is None:
5827
+ logging.info(_('No laz grid - Aborting !'))
5769
5828
  return
5770
5829
 
5771
5830
  if array is None:
@@ -5801,15 +5860,15 @@ class WolfMapViewer(wx.Frame):
5801
5860
  curbounds = [[curx, curx + chunk_size], [cury, cury + chunk_size]]
5802
5861
 
5803
5862
  logging.info(_('Scan {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
5804
- self.mylazdata = self.mylazgrid.scan(curbounds)
5863
+ mylazdata = self.mylazgrid.scan(curbounds)
5805
5864
 
5806
- if len(self.mylazdata) == 0:
5865
+ if len(mylazdata) == 0:
5807
5866
  continue
5808
5867
 
5809
5868
  # Test codes
5810
5869
  data = {}
5811
5870
  for curcode in used_codes:
5812
- data[curcode] = self.mylazdata[self.mylazdata[:, 3] == curcode]
5871
+ data[curcode] = mylazdata[mylazdata[:, 3] == curcode]
5813
5872
 
5814
5873
  # Treat data for each code
5815
5874
  for curdata in data.values():
@@ -5820,7 +5879,7 @@ class WolfMapViewer(wx.Frame):
5820
5879
  logging.info(_('Code {} : {} points'.format(curdata[0,3], curdata.shape[0])))
5821
5880
 
5822
5881
  # get i,j from x,y
5823
- i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1]) #= np.float32(self.mylazdata[:, 2])
5882
+ i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1])
5824
5883
 
5825
5884
  # keep only valid points -- inside the array
5826
5885
  used = np.where((i >=0) & (i < array.nbx) & (j >=0) & (j < array.nby))[0]
@@ -5877,26 +5936,48 @@ class WolfMapViewer(wx.Frame):
5877
5936
 
5878
5937
  logging.info(_('Counting done'))
5879
5938
 
5880
- def init_laz_from_numpy(self, fn=None):
5881
- """ Read LAZ data stored in numpy array"""
5939
+ def init_laz_from_lazlasnpz(self, fn=None):
5940
+ """ Read LAZ data stored in one file
5941
+
5942
+ :param fn: filename (extension .laz, .las, .npz)
5943
+ """
5882
5944
 
5883
5945
  if fn is None:
5884
5946
  filternpz = "npz (*.npz)|*.npz|LAZ (*.laz)|*.laz|LAS (*.las)|*.las|all (*.*)|*.*"
5885
- dlg = wx.FileDialog(None, _('Choose LAS file'), wildcard=filternpz)
5947
+ dlg = wx.FileDialog(None, _('Choose a file containing LAS data'), wildcard=filternpz)
5886
5948
  ret = dlg.ShowModal()
5887
5949
  if ret != wx.ID_OK:
5950
+ dlg.Destroy()
5888
5951
  return
5889
5952
 
5890
5953
  fn = dlg.GetPath()
5954
+ dlg.Destroy()
5891
5955
 
5892
- self.mylazdata = read_laz(fn)
5893
- # self.mylazdata_colors = Classification_LAZ()
5894
- # self.mylazdata_colors.init_2023()
5956
+ self.mylazdata.append(Base_LAZ_Data())
5957
+ self.active_laz = self.mylazdata[-1]
5958
+ self.active_laz.from_file(fn)
5959
+
5960
+ logging.info(_('LAZ data read from file : ')+ fn)
5961
+ logging.info(_('Stored in internal variable'))
5895
5962
 
5896
5963
  if self.linked:
5897
5964
  if len(self.linkedList) > 0:
5898
5965
  for curframe in self.linkedList:
5899
- curframe.mylazdata = self.mylazdata
5966
+ if not curframe is self:
5967
+ curframe.mylazdata.append(self.active_laz)
5968
+
5969
+ def _choice_laz_classification(self):
5970
+
5971
+ dlg = wx.SingleChoiceDialog(None, _('Choose the classification'), _('Classification'), ['SPW-Geofit 2023', 'SPW 2013-2014'], wx.CHOICEDLG_STYLE)
5972
+ ret = dlg.ShowModal()
5973
+ if ret != wx.ID_OK:
5974
+ dlg.Destroy()
5975
+ return None
5976
+
5977
+ classification = dlg.GetStringSelection()
5978
+ dlg.Destroy()
5979
+
5980
+ return classification
5900
5981
 
5901
5982
  def init_laz_from_gridinfos(self, dirlaz:str = None, classification:Literal['SPW-Geofit 2023', 'SPW 2013-2014'] = 'SPW-Geofit 2023'):
5902
5983
 
@@ -5911,15 +5992,13 @@ class WolfMapViewer(wx.Frame):
5911
5992
  self.mylazgrid = xyz_laz_grids(dirlaz)
5912
5993
 
5913
5994
  if classification not in ['SPW-Geofit 2023', 'SPW 2013-2014']:
5914
- dlg = wx.SingleChoiceDialog(None, _('Choose the classification'), _('Classification'), ['SPW-Geofit 2023', 'SPW 2013-2014'], wx.CHOICEDLG_STYLE)
5915
- ret = dlg.ShowModal()
5916
- if ret != wx.ID_OK:
5917
- dlg.Destroy()
5918
- return
5919
- classification = dlg.GetStringSelection()
5920
- dlg.Destroy()
5921
5995
 
5922
- if classification == 'SPW 2013-2014':
5996
+ classification = self._choice_laz_classification()
5997
+
5998
+ if classification is None:
5999
+ logging.warning(_('No classification chosen - Abort !'))
6000
+ return
6001
+ elif classification == 'SPW 2013-2014':
5923
6002
  self.mylazgrid.colors.init_2013()
5924
6003
  else:
5925
6004
  self.mylazgrid.colors.init_2023()
@@ -6129,15 +6208,15 @@ class WolfMapViewer(wx.Frame):
6129
6208
  def _select_laz_source(self):
6130
6209
  """ Select laz source """
6131
6210
 
6132
- if self.mylazdata is None and self.mylazgrid is None:
6211
+ if self.active_laz is None and self.mylazgrid is None:
6133
6212
  logging.warning(_('No LAZ data loaded !'))
6134
6213
  return None
6135
- elif self.mylazdata is None:
6214
+ elif self.active_laz is None:
6136
6215
  laz_source = self.mylazgrid
6137
6216
  elif self.mylazgrid is None:
6138
- laz_source = self.mylazdata
6217
+ laz_source = self.active_laz
6139
6218
  else:
6140
- choices = [_('From current loaded data'), _('From GridInfos')]
6219
+ choices = [_('From active LAZ data'), _('From newly extracted data')]
6141
6220
  dlg = wx.SingleChoiceDialog(None, _("Pick a data source"), "Choices", choices)
6142
6221
  ret = dlg.ShowModal()
6143
6222
  if ret == wx.ID_CANCEL:
@@ -6149,12 +6228,32 @@ class WolfMapViewer(wx.Frame):
6149
6228
  dlg.Destroy()
6150
6229
 
6151
6230
  if idx == 0:
6152
- laz_source = self.mylazdata
6231
+ laz_source = self.active_laz
6153
6232
  else:
6154
6233
  laz_source = self.mylazgrid
6155
6234
 
6156
6235
  return laz_source
6157
6236
 
6237
+ def _choice_laz_colormap(self) -> int:
6238
+
6239
+ choices, ass_values = choices_laz_colormap()
6240
+ dlg = wx.SingleChoiceDialog(None, _("Pick a colormap"), "Choices", choices)
6241
+
6242
+ if self.active_laz is not None:
6243
+ dlg.SetSelection(self.active_laz.associated_color)
6244
+
6245
+ ret = dlg.ShowModal()
6246
+ if ret == wx.ID_CANCEL:
6247
+ dlg.Destroy()
6248
+ return
6249
+
6250
+ colormap = dlg.GetStringSelection()
6251
+ idx = choices.index(colormap)
6252
+ dlg.Destroy()
6253
+
6254
+ return ass_values[idx]
6255
+
6256
+
6158
6257
  def OnMenubar(self, event: wx.MenuEvent):
6159
6258
  """
6160
6259
  Gestion des clicks sur le menu quel que soit le niveau
@@ -6801,18 +6900,20 @@ class WolfMapViewer(wx.Frame):
6801
6900
 
6802
6901
  self.save_project(filename, absolute= abspath)
6803
6902
 
6804
- elif itemlabel == _('Initialize from npz'):
6805
- self.init_laz_from_numpy()
6903
+ elif itemlabel == _('Initialize from laz, las or npz'):
6904
+ self.init_laz_from_lazlasnpz()
6806
6905
 
6807
- elif itemlabel == _('Initialize from GridInfos'):
6906
+ elif itemlabel == _('Initialize from directory'):
6808
6907
  self.init_laz_from_gridinfos()
6809
6908
 
6810
6909
  elif itemlabel == _('Create cloud points from bridges'):
6811
- if self.mylazdata is None:
6812
- self.init_laz_from_numpy()
6813
6910
 
6814
- mybridges = self.mylazdata[np.where(self.mylazdata[:, 3] == 10)]
6911
+ if self.active_laz is None:
6912
+ self.init_laz_from_lazlasnpz()
6913
+
6914
+ mybridges = self.active_laz.get_data_class(10)
6815
6915
  mycloud = cloud_vertices()
6916
+
6816
6917
  mycloud.init_from_nparray(mybridges)
6817
6918
  mycloud.myprop.style = 2
6818
6919
  mycloud.myprop.color = getIfromRGB([255, 102, 102])
@@ -6827,11 +6928,12 @@ class WolfMapViewer(wx.Frame):
6827
6928
 
6828
6929
  elif itemlabel == _('Create cloud points from buildings'):
6829
6930
 
6830
- if self.mylazdata is None:
6831
- self.init_laz_from_numpy()
6931
+ if self.active_laz is None:
6932
+ self.init_laz_from_lazlasnpz()
6832
6933
 
6833
- mybuildings = self.mylazdata[np.where(self.mylazdata[:, 3] == 1)]
6934
+ mybuildings = self.active_laz.get_data_class(1)
6834
6935
  mycloud = cloud_vertices()
6936
+
6835
6937
  mycloud.init_from_nparray(mybuildings)
6836
6938
  mycloud.myprop.style = 2
6837
6939
  mycloud.myprop.color = getIfromRGB([102, 102, 102])
@@ -6843,23 +6945,15 @@ class WolfMapViewer(wx.Frame):
6843
6945
  else:
6844
6946
  self.add_object('cloud', newobj=mycloud, ToCheck=True, id='Buildings')
6845
6947
 
6948
+ elif itemlabel == _('Create cloud points from specified classes'):
6949
+ pass
6950
+
6846
6951
  elif itemlabel == _('Create LAZ viewer'):
6847
6952
 
6848
6953
  laz_source = self._select_laz_source()
6849
6954
  if laz_source is None:
6850
6955
  return
6851
6956
 
6852
- choices, ass_values = choices_laz_colormap()
6853
- dlg = wx.SingleChoiceDialog(None, _("Pick a colormap"), "Choices", choices)
6854
- ret = dlg.ShowModal()
6855
- if ret == wx.ID_CANCEL:
6856
- dlg.Destroy()
6857
- return
6858
-
6859
- colormap = dlg.GetStringSelection()
6860
- idx = choices.index(colormap)
6861
- dlg.Destroy()
6862
-
6863
6957
  if laz_source is self.mylazgrid:
6864
6958
  if self.mylazgrid is None:
6865
6959
  logging.warning(_('No gridded LAZ data loaded !'))
@@ -6867,9 +6961,43 @@ class WolfMapViewer(wx.Frame):
6867
6961
  autoscale=False
6868
6962
  self.clip_laz_gridded()
6869
6963
 
6870
- self.myviewer = myviewer(self.mylazdata, ass_values[idx], palette_classif = self.mylazgrid.colors)
6964
+ self.active_laz.create_viewer(self._choice_laz_colormap(), self.mylazgrid.colors)
6965
+ self.myviewerslaz.append(self.active_laz.viewer)
6966
+ self.active_viewerlaz = self.myviewerslaz[-1]
6967
+
6968
+ # self.myviewer = myviewer(self.active_laz.data, ass_values[idx], palette_classif = self.mylazgrid.colors)
6871
6969
  else:
6872
- self.myviewer = myviewer(laz_source, ass_values[idx]) #, palette_classif = self.mylazdata_colors)
6970
+ self.active_laz.create_viewer(classification= self.mylazgrid.colors)
6971
+ self.myviewerslaz.append(self.active_laz.viewer)
6972
+ self.active_viewerlaz = self.myviewerslaz[-1]
6973
+
6974
+ # self.myviewer = myviewer(laz_source.data, ass_values[idx], palette_classif= laz_source.classification)
6975
+
6976
+ elif itemlabel == _('Filter data based on codes'):
6977
+
6978
+ self.filter_active_laz()
6979
+
6980
+ elif itemlabel == _('Descimate LAZ data'):
6981
+
6982
+ if self.active_laz is None:
6983
+ return
6984
+
6985
+ # Choose a decimation factor - integer
6986
+ dlg = wx.NumberEntryDialog(None, _('Your dataset contains {} points.\nWould you like to decimate?').format(self.active_laz.num_points),
6987
+ _('Decaimate factor'), _('Decimation'), 0, 0, 100)
6988
+
6989
+ ret = dlg.ShowModal()
6990
+
6991
+ if ret == wx.ID_CANCEL:
6992
+ dlg.Destroy()
6993
+ return
6994
+
6995
+ decimate_fact = dlg.GetValue()
6996
+ dlg.Destroy()
6997
+
6998
+ if decimate_fact > 0:
6999
+ self.active_laz.decimate(decimate_fact)
7000
+ logging.info(_('New count : {}').format(self.active_laz.num_points))
6873
7001
 
6874
7002
  elif itemlabel == _('Clip LAZ grid on current zoom'):
6875
7003
 
@@ -6879,10 +7007,11 @@ class WolfMapViewer(wx.Frame):
6879
7007
 
6880
7008
  self.clip_laz_gridded()
6881
7009
 
6882
- if self.mylazdata is None:
7010
+ if self.active_laz is None:
7011
+ logging.error(_('No data found'))
6883
7012
  return
6884
7013
 
6885
- if self.mylazdata.shape[0] > 100_000_000:
7014
+ if self.active_laz.data.shape[0] > 100_000_000:
6886
7015
 
6887
7016
  # Choose a decimation factor - integer
6888
7017
  dlg = wx.NumberEntryDialog(None, _('Your data selection is very large (>100 M)\nWould you like to decimate?'),
@@ -7991,7 +8120,7 @@ class WolfMapViewer(wx.Frame):
7991
8120
  'weirs',
7992
8121
  'vector',
7993
8122
  'tiles', 'tilescomp'
7994
- 'cloud',
8123
+ 'cloud', 'laz',
7995
8124
  'triangulation',
7996
8125
  'cross_sections',
7997
8126
  'other',
@@ -8011,12 +8140,13 @@ class WolfMapViewer(wx.Frame):
8011
8140
  Add object to current Frame/Drawing area
8012
8141
  """
8013
8142
 
8014
- filterArray = "All supported formats|*.bin;*.tif;*.tiff;*.top;*.flt;*.npy;*.npz|bin (*.bin)|*.bin|Elevation WOLF2D (*.top)|*.top|Geotif (*.tif)|*.tif|Float ESRI (*.flt)|*.flt|Numpy (*.npy)|*.npy|Numpy named arrays(*.npz)|*.npz|all (*.*)|*.*"
8143
+ filterArray = "All supported formats|*.bin;*.tif;*.tiff;*.top;*.flt;*.npy;*.npz;*.vrt|bin (*.bin)|*.bin|Elevation WOLF2D (*.top)|*.top|Geotif (*.tif)|*.tif|Float ESRI (*.flt)|*.flt|Numpy (*.npy)|*.npy|Numpy named arrays(*.npz)|*.npz|all (*.*)|*.*"
8015
8144
  filterjson = "json (*.json)|*.json|all (*.*)|*.*"
8016
8145
  filterall = "all (*.*)|*.*"
8017
8146
  filterres2d = "all (*.*)|*.*"
8018
8147
  filterVector = "All supported formats|*.vec;*.vecz;*.dxf;*.shp|vec (*.vec)|*.vec|vecz (*.vecz)|*.vecz|dxf (*.dxf)|*.dxf|shp (*.shp)|*.shp|all (*.*)|*.*"
8019
8148
  filterCloud = "xyz (*.xyz)|*.xyz|dxf (*.dxf)|*.dxf|text (*.txt)|*.txt|shp (*.shp)|*.shp|all (*.*)|*.*"
8149
+ filterlaz = "laz (*.laz)|*.laz|las (*.las)|*.las|Numpy (*.npz)|*.npz|all (*.*)|*.*"
8020
8150
  filtertri = "tri (*.tri)|*.tri|text (*.txt)|*.txt|dxf (*.dxf)|*.dxf|gltf (*.gltf)|*.gltf|gltf binary (*.glb)|*.glb|*.*'all (*.*)|*.*"
8021
8151
  filterCs = "vecz WOLF (*.vecz)|*.vecz|txt 2022 (*.txt)|*.txt|WOLF (*.sxy)|*.sxy|text 2000 (*.txt)|*.txt|all (*.*)|*.*"
8022
8152
  filterimage = "Geotif (*.tif)|*.tif|all (*.*)|*.*"
@@ -8043,6 +8173,8 @@ class WolfMapViewer(wx.Frame):
8043
8173
  file = wx.FileDialog(self, "Choose file", wildcard=filterVector)
8044
8174
  elif which.lower() == 'cloud':
8045
8175
  file = wx.FileDialog(self, "Choose file", wildcard=filterCloud)
8176
+ elif which.lower() == 'laz':
8177
+ file = wx.FileDialog(self, "Choose file", wildcard=filterlaz)
8046
8178
  elif which.lower() == 'triangulation':
8047
8179
  file = wx.FileDialog(self, "Choose file", wildcard=filtertri)
8048
8180
  elif which.lower() == 'cross_sections':
@@ -8543,6 +8675,19 @@ class WolfMapViewer(wx.Frame):
8543
8675
  self.myvectors.append(newobj)
8544
8676
  newobj.mapviewer = self
8545
8677
 
8678
+ elif which.lower() =='laz':
8679
+ curdict = self.mylazdata
8680
+ curtree = self.myitemslaz
8681
+
8682
+ if newobj is None:
8683
+ newobj = Base_LAZ_Data(mapviewer=self)
8684
+ newobj.from_file(filename)
8685
+
8686
+ self.mylazdata.append(newobj)
8687
+ self.active_laz = newobj
8688
+
8689
+ newobj.set_mapviewer(self)
8690
+
8546
8691
  elif which.lower() == 'cloud':
8547
8692
 
8548
8693
  curdict = self.myclouds
@@ -8784,6 +8929,8 @@ class WolfMapViewer(wx.Frame):
8784
8929
  return self.mywmsfore
8785
8930
  elif drawing_type == draw_type.IMAGESTILES:
8786
8931
  return self.myimagestiles
8932
+ elif drawing_type == draw_type.LAZ:
8933
+ return self.mylazdata
8787
8934
  else:
8788
8935
  logging.error('Unknown drawing type : ' + drawing_type)
8789
8936
  return None
@@ -9217,7 +9364,7 @@ class WolfMapViewer(wx.Frame):
9217
9364
  elif text == _('Properties'):
9218
9365
 
9219
9366
  myobj = self.selected_object
9220
- if type(myobj) in [WolfArray, WolfArrayMB, WolfArrayMNAP, Zones, Wolfresults_2D, wolfres2DGPU, Particle_system, Picc_data, Cadaster_data, hydrometry_wolfgui, Bridge, Weir]:
9367
+ if type(myobj) in [WolfArray, WolfArrayMB, WolfArrayMNAP, Zones, Wolfresults_2D, wolfres2DGPU, Particle_system, Picc_data, Cadaster_data, hydrometry_wolfgui, Bridge, Weir, Base_LAZ_Data]:
9221
9368
  myobj.show_properties()
9222
9369
 
9223
9370
  elif isinstance(myobj, cloud_vertices):
@@ -9365,6 +9512,92 @@ class WolfMapViewer(wx.Frame):
9365
9512
  self.selected_object.export_active_zone_to_shapefile(fdlg.GetPath())
9366
9513
  fdlg.Destroy()
9367
9514
 
9515
+ elif _('Set colormap') in text:
9516
+
9517
+ if isinstance(self.selected_object, Base_LAZ_Data):
9518
+ self.selected_object.associated_color = self._choice_laz_colormap()
9519
+
9520
+ elif _('Edit colormap') in text:
9521
+
9522
+ if isinstance(self.selected_object, Base_LAZ_Data):
9523
+ self.selected_object.interactive_update_colors()
9524
+
9525
+ elif _('Set classification') in text:
9526
+
9527
+ if isinstance(self.selected_object, Base_LAZ_Data):
9528
+ self.selected_object.set_classification(self._choice_laz_classification())
9529
+
9530
+ elif _('All to cloud') in text:
9531
+
9532
+ if isinstance(self.selected_object, Base_LAZ_Data):
9533
+
9534
+ if self.selected_object.num_points > 100000:
9535
+ dlg = wx.MessageDialog(None, _('The number of points is high, it could take some time to convert to cloud.\nDo you want to continue ?'), _('Warning'), wx.YES_NO | wx.NO_DEFAULT)
9536
+ ret = dlg.ShowModal()
9537
+
9538
+ if ret != wx.ID_YES:
9539
+ dlg.Destroy()
9540
+
9541
+ return
9542
+
9543
+ newcloud = cloud_vertices()
9544
+ newcloud.init_from_nparray(self.selected_object.xyz)
9545
+ self.add_object('cloud', newobj=newcloud, id=self.selected_object.idx + '_cloud')
9546
+
9547
+ elif _('Selection to cloud') in text:
9548
+
9549
+ if isinstance(self.selected_object, Base_LAZ_Data):
9550
+
9551
+ xyz = self.selected_object.xyz_selected
9552
+ if xyz.shape[0] ==0:
9553
+ logging.warning('No points selected')
9554
+ return
9555
+
9556
+ if xyz.shape[0] > 100000:
9557
+ dlg = wx.MessageDialog(None, _('The number of points is high, it could take some time to convert to cloud.\nDo you want to continue ?'), _('Warning'), wx.YES_NO | wx.NO_DEFAULT)
9558
+ ret = dlg.ShowModal()
9559
+
9560
+ if ret != wx.ID_YES:
9561
+ dlg.Destroy()
9562
+
9563
+ return
9564
+
9565
+ newcloud = cloud_vertices()
9566
+ newcloud.init_from_nparray(xyz)
9567
+ self.add_object('cloud', newobj=newcloud, id=self.selected_object.idx + '_cloud_sel')
9568
+
9569
+ elif _('Play') in text:
9570
+
9571
+ if isinstance(self.selected_object, Base_LAZ_Data):
9572
+ self.selected_object.play_flight()
9573
+
9574
+ elif _('Record') in text:
9575
+
9576
+ if isinstance(self.selected_object, Base_LAZ_Data):
9577
+
9578
+ dlg = wx.DirDialog(self, _('Choose a directory to save the video'), style=wx.DD_DEFAULT_STYLE)
9579
+ if dlg.ShowModal() == wx.ID_OK:
9580
+ self.selected_object.record_flight(dlg.GetPath())
9581
+
9582
+ dlg.Destroy()
9583
+
9584
+ elif _('Load flight') in text:
9585
+
9586
+ if isinstance(self.selected_object, Base_LAZ_Data):
9587
+ dlg = wx.FileDialog(self, _('Choose a file to load the flight'), wildcard='JSON (*.json)|*.json|All (*.*)|*.*', style=wx.FD_OPEN)
9588
+ if dlg.ShowModal() == wx.ID_OK:
9589
+ self.selected_object.load_flight(dlg.GetPath())
9590
+
9591
+ dlg.Destroy()
9592
+
9593
+ elif _('Save flight') in text:
9594
+
9595
+ if isinstance(self.selected_object, Base_LAZ_Data):
9596
+ dlg = wx.FileDialog(self, _('Choose a file to save the flight'), wildcard='JSON (*.json)|*.json|All (*.*)|*.*', style=wx.FD_SAVE)
9597
+ if dlg.ShowModal() == wx.ID_OK:
9598
+ self.selected_object.save_flight(dlg.GetPath())
9599
+
9600
+ dlg.Destroy()
9368
9601
 
9369
9602
  def OnClose(self, event):
9370
9603
  """ Close the application """
@@ -10151,6 +10384,13 @@ class WolfMapViewer(wx.Frame):
10151
10384
  if ctrl:
10152
10385
  myobj.show_properties()
10153
10386
 
10387
+ elif type(myobj) == Base_LAZ_Data:
10388
+
10389
+ self.active_laz = myobj
10390
+
10391
+ if ctrl:
10392
+ myobj.show_properties()
10393
+
10154
10394
  elif type(myobj) == Bridge:
10155
10395
  self.active_bridge = myobj
10156
10396
 
@@ -11825,6 +12065,10 @@ class WolfMapViewer(wx.Frame):
11825
12065
  self.mousex = self.mousex + self.width / 10.
11826
12066
  self.setbounds()
11827
12067
 
12068
+ elif key == ord('A'):
12069
+ if self.active_laz is not None:
12070
+ self.active_laz.add_pose_in_memory()
12071
+
11828
12072
  def paste_values(self,fromarray:WolfArray):
11829
12073
  """ Paste selected values from a WolfArray to the active array """
11830
12074
 
@@ -11875,6 +12119,19 @@ class WolfMapViewer(wx.Frame):
11875
12119
  tracks.append(_('Export active zone to Shape file'))
11876
12120
  tracks.append(_('Rebin'))
11877
12121
  tracks.append(_('Set NullValue'))
12122
+ tracks.append(_('Set colormap'))
12123
+ tracks.append(_('Edit colormap'))
12124
+ tracks.append(_('Set classification'))
12125
+ tracks.append(_('Convert to...'))
12126
+ tracks.append(_('All to cloud'))
12127
+ tracks.append(_('Selection to cloud'))
12128
+
12129
+ tracks.append(_('Colormap'))
12130
+ tracks.append(_('Movie'))
12131
+ tracks.append(_('Play'))
12132
+ tracks.append(_('Record'))
12133
+ tracks.append(_('Load flight'))
12134
+ tracks.append(_('Save flight'))
11878
12135
 
11879
12136
  # Récupération des items du menu contextuel
11880
12137
  menuitems = self.popupmenu.GetMenuItems()
@@ -11917,6 +12174,29 @@ class WolfMapViewer(wx.Frame):
11917
12174
  self.popupmenu.Append(wx.ID_ANY, _('Export to Shape file'), _('Export to Shape file'))
11918
12175
  self.popupmenu.Append(wx.ID_ANY, _('Export active zone to Shape file'), _('Export active zone to Shape file'))
11919
12176
 
12177
+ if isinstance(self.selected_object, Base_LAZ_Data):
12178
+
12179
+ colrmapmenu = wx.Menu()
12180
+ self.popupmenu.AppendSubMenu(colrmapmenu, _('Colormap'))
12181
+
12182
+ colrmapmenu.Append(wx.ID_ANY, _('Set colormap'), _('Change colormap'))
12183
+ colrmapmenu.Append(wx.ID_ANY, _('Edit colormap'), _('Edit colormap'))
12184
+ colrmapmenu.Append(wx.ID_ANY, _('Set classification'), _('Change classification'))
12185
+
12186
+ converttomenu = wx.Menu()
12187
+ self.popupmenu.AppendSubMenu(converttomenu, _('Convert to...'))
12188
+
12189
+ converttomenu.Append(wx.ID_ANY, _('All to cloud'), _('Convert all to cloud'))
12190
+ converttomenu.Append(wx.ID_ANY, _('Selection to cloud'), _('Convert selection to cloud'))
12191
+
12192
+ moviemenu = wx.Menu()
12193
+ self.popupmenu.AppendSubMenu(moviemenu, _('Movie'))
12194
+
12195
+ moviemenu.Append(wx.ID_ANY, _('Play'), _('Play'))
12196
+ moviemenu.Append(wx.ID_ANY, _('Record'), _('Record'))
12197
+ moviemenu.Append(wx.ID_ANY, _('Load flight'), _('Load flight'))
12198
+ moviemenu.Append(wx.ID_ANY, _('Save flight'), _('Save flight'))
12199
+
11920
12200
  self.treelist.PopupMenu(self.popupmenu)
11921
12201
 
11922
12202
  def update(self):