BERATools 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. beratools/__init__.py +8 -3
  2. beratools/core/{algo_footprint_rel.py → algo_canopy_footprint_exp.py} +176 -139
  3. beratools/core/algo_centerline.py +61 -77
  4. beratools/core/algo_common.py +48 -57
  5. beratools/core/algo_cost.py +18 -25
  6. beratools/core/algo_dijkstra.py +37 -45
  7. beratools/core/algo_line_grouping.py +100 -100
  8. beratools/core/algo_merge_lines.py +40 -8
  9. beratools/core/algo_split_with_lines.py +289 -304
  10. beratools/core/algo_vertex_optimization.py +25 -46
  11. beratools/core/canopy_threshold_relative.py +755 -0
  12. beratools/core/constants.py +8 -9
  13. beratools/{tools → core}/line_footprint_functions.py +411 -258
  14. beratools/core/logger.py +18 -2
  15. beratools/core/tool_base.py +17 -75
  16. beratools/gui/assets/BERALogo.ico +0 -0
  17. beratools/gui/assets/BERA_Splash.gif +0 -0
  18. beratools/gui/assets/BERA_WizardImage.png +0 -0
  19. beratools/gui/assets/beratools.json +475 -2171
  20. beratools/gui/bt_data.py +585 -234
  21. beratools/gui/bt_gui_main.py +129 -91
  22. beratools/gui/main.py +4 -7
  23. beratools/gui/tool_widgets.py +530 -354
  24. beratools/tools/__init__.py +0 -7
  25. beratools/tools/{line_footprint_absolute.py → canopy_footprint_absolute.py} +81 -56
  26. beratools/tools/canopy_footprint_exp.py +113 -0
  27. beratools/tools/centerline.py +30 -37
  28. beratools/tools/check_seed_line.py +127 -0
  29. beratools/tools/common.py +65 -586
  30. beratools/tools/{line_footprint_fixed.py → ground_footprint.py} +140 -117
  31. beratools/tools/line_footprint_relative.py +64 -35
  32. beratools/tools/tool_template.py +48 -40
  33. beratools/tools/vertex_optimization.py +20 -34
  34. beratools/utility/env_checks.py +53 -0
  35. beratools/utility/spatial_common.py +210 -0
  36. beratools/utility/tool_args.py +138 -0
  37. beratools-0.2.4.dist-info/METADATA +134 -0
  38. beratools-0.2.4.dist-info/RECORD +50 -0
  39. {beratools-0.2.3.dist-info → beratools-0.2.4.dist-info}/WHEEL +1 -1
  40. beratools-0.2.4.dist-info/entry_points.txt +3 -0
  41. beratools-0.2.4.dist-info/licenses/LICENSE +674 -0
  42. beratools/core/algo_tiler.py +0 -428
  43. beratools/gui/__init__.py +0 -11
  44. beratools/gui/batch_processing_dlg.py +0 -513
  45. beratools/gui/map_window.py +0 -162
  46. beratools/tools/Beratools_r_script.r +0 -1120
  47. beratools/tools/Ht_metrics.py +0 -116
  48. beratools/tools/batch_processing.py +0 -136
  49. beratools/tools/canopy_threshold_relative.py +0 -672
  50. beratools/tools/canopycostraster.py +0 -222
  51. beratools/tools/fl_regen_csf.py +0 -428
  52. beratools/tools/forest_line_attributes.py +0 -408
  53. beratools/tools/line_grouping.py +0 -45
  54. beratools/tools/ln_relative_metrics.py +0 -615
  55. beratools/tools/r_cal_lpi_elai.r +0 -25
  56. beratools/tools/r_generate_pd_focalraster.r +0 -101
  57. beratools/tools/r_interface.py +0 -80
  58. beratools/tools/r_point_density.r +0 -9
  59. beratools/tools/rpy_chm2trees.py +0 -86
  60. beratools/tools/rpy_dsm_chm_by.py +0 -81
  61. beratools/tools/rpy_dtm_by.py +0 -63
  62. beratools/tools/rpy_find_cellsize.py +0 -43
  63. beratools/tools/rpy_gnd_csf.py +0 -74
  64. beratools/tools/rpy_hummock_hollow.py +0 -85
  65. beratools/tools/rpy_hummock_hollow_raster.py +0 -71
  66. beratools/tools/rpy_las_info.py +0 -51
  67. beratools/tools/rpy_laz2las.py +0 -40
  68. beratools/tools/rpy_lpi_elai_lascat.py +0 -466
  69. beratools/tools/rpy_normalized_lidar_by.py +0 -56
  70. beratools/tools/rpy_percent_above_dbh.py +0 -80
  71. beratools/tools/rpy_points2trees.py +0 -88
  72. beratools/tools/rpy_vegcoverage.py +0 -94
  73. beratools/tools/tiler.py +0 -48
  74. beratools/tools/zonal_threshold.py +0 -144
  75. beratools-0.2.3.dist-info/METADATA +0 -108
  76. beratools-0.2.3.dist-info/RECORD +0 -74
  77. beratools-0.2.3.dist-info/entry_points.txt +0 -2
  78. beratools-0.2.3.dist-info/licenses/LICENSE +0 -22
@@ -1,513 +0,0 @@
1
- """
2
- Copyright (C) 2025 Applied Geospatial Research Group.
3
-
4
- This script is licensed under the GNU General Public License v3.0.
5
- See <https://gnu.org/licenses/gpl-3.0> for full license details.
6
-
7
- Author: Richard Zeng
8
-
9
- Description:
10
- This script is part of the BERA Tools.
11
- Webpage: https://github.com/appliedgrg/beratools
12
-
13
- Batch processing dialog.
14
- """
15
- import sys
16
- import pandas as pd
17
- from PyQt5 import QtCore
18
- from PyQt5 import QtWidgets
19
- from PyQt5 import QtGui, QtPrintSupport
20
-
21
- from beratools.gui.tool_widgets import ToolWidgets
22
- from beratools.gui.bt_data import BTData
23
- bt = BTData()
24
-
25
-
26
- class _PandasModel(QtCore.QAbstractTableModel):
27
- def __init__(self, df=pd.DataFrame(), parent=None):
28
- QtCore.QAbstractTableModel.__init__(self, parent=None)
29
- self._df = df
30
- self.setChanged = False
31
- self.dataChanged.connect(self.setModified)
32
-
33
- def setModified(self):
34
- self.setChanged = True
35
- print(self.setChanged)
36
-
37
- def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
38
- if role != QtCore.Qt.DisplayRole:
39
- return QtCore.QVariant()
40
- if orientation == QtCore.Qt.Horizontal:
41
- try:
42
- return self._df.columns.tolist()[section]
43
- except (IndexError,):
44
- return QtCore.QVariant()
45
- elif orientation == QtCore.Qt.Vertical:
46
- try:
47
- return self._df.index.tolist()[section]
48
- except (IndexError,):
49
- return QtCore.QVariant()
50
-
51
- def flags(self, index):
52
- return (
53
- QtCore.Qt.ItemIsEnabled
54
- | QtCore.Qt.ItemIsSelectable
55
- | QtCore.Qt.ItemIsEditable
56
- )
57
-
58
- def data(self, index, role=QtCore.Qt.DisplayRole):
59
- if index.isValid():
60
- if role == QtCore.Qt.EditRole:
61
- return self._df.values[index.row()][index.column()]
62
- elif role == QtCore.Qt.DisplayRole:
63
- return self._df.values[index.row()][index.column()]
64
- return None
65
-
66
- def data_row_dict(self, row):
67
- return self._df.iloc[row].to_dict()
68
-
69
- def setData(self, index, value, role):
70
- row = self._df.index[index.row()]
71
- col = self._df.columns[index.column()]
72
- self._df.values[row][col] = value
73
- self.dataChanged.emit(index, index)
74
- return True
75
-
76
- def rowCount(self, parent=QtCore.QModelIndex()):
77
- return len(self._df.index)
78
-
79
- def columnCount(self, parent=QtCore.QModelIndex()):
80
- return len(self._df.columns)
81
-
82
- def sort(self, column, order):
83
- col_name = self._df.columns.tolist()[column]
84
- self.layoutAboutToBeChanged.emit()
85
- self._df.sort_values(
86
- col_name, ascending=order == QtCore.Qt.AscendingOrder, inplace=True
87
- )
88
- self._df.reset_index(inplace=True, drop=True)
89
- self.layoutChanged.emit()
90
-
91
- def insertRows(self, position, rows=1, index=QtCore.QModelIndex()):
92
- self.beginInsertRows(QtCore.QModelIndex(), position, position + rows - 1)
93
- for i in range(rows):
94
- self._df.loc[len(self._df)] = self.default_record
95
-
96
- self.endInsertRows()
97
- return True
98
-
99
- def removeRows(self, position, rows=1, index=QtCore.QModelIndex()):
100
- self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)
101
- for i in range(rows):
102
- self._df.drop(self._df.index[position + i], inplace=True)
103
- print('removed: {}'.format(position + i))
104
-
105
- self.endRemoveRows()
106
- return True
107
-
108
- def updateRow(self, row, row_data):
109
- self._df.loc[row] = row_data
110
- self.dataChanged(row, 0)
111
-
112
- def save_csv(self, csv_file):
113
- self._df.to_csv(csv_file, index=False)
114
-
115
-
116
- class BPDialog(QtWidgets.QDialog):
117
- """Batch Processing Dialog."""
118
-
119
- # signals
120
- signal_update_tool_widgets = QtCore.pyqtSignal(int)
121
-
122
- def __init__(self, tool_name, parent=None):
123
- super(BPDialog, self).__init__(parent)
124
- self.setWindowTitle('Batch Processing')
125
- self.MaxRecentFiles = 5
126
- self.window_list = []
127
- self.recent_files = []
128
- self.settings = QtCore.QSettings('Richard Zeng', 'Batch Processing')
129
- self.filename = ""
130
- self.setGeometry(0, 0, 800, 600)
131
-
132
- # table view
133
- self.table_view = QtWidgets.QTableView()
134
- self.table_view.verticalHeader().setVisible(True)
135
- self.model = _PandasModel()
136
- self.table_view.setModel(self.model)
137
- self.table_view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
138
- self.table_view.setSelectionBehavior(self.table_view.SelectRows)
139
- self.table_view.setSelectionMode(self.table_view.ExtendedSelection)
140
-
141
- self.table_view.clicked.connect(self.table_view_clicked)
142
- self.table_view.verticalHeader().sectionClicked.connect(
143
- self.table_view_vertical_header_clicked
144
- )
145
- QtWidgets.QShortcut(
146
- QtCore.Qt.Key_Up, self.table_view, activated=self.table_view_key_up
147
- )
148
- QtWidgets.QShortcut(
149
- QtCore.Qt.Key_Down, self.table_view, activated=self.table_view_key_down
150
- )
151
-
152
- # create form
153
- self.tool_name = tool_name
154
- tool_args = bt.get_bera_tool_args(self.tool_name)
155
- self.tool_widgets = ToolWidgets(tool_name, tool_args, False)
156
-
157
- # self.createToolBar()
158
- hbox_widgets = QtWidgets.QHBoxLayout()
159
- hbox_widgets.addWidget(self.table_view, 2)
160
- hbox_widgets.addWidget(self.tool_widgets, 1)
161
-
162
- # Add project, record related button box
163
- self.project_btns = QtWidgets.QHBoxLayout()
164
- open_button = QtWidgets.QPushButton('Open')
165
- save_button = QtWidgets.QPushButton('Save')
166
- save_as_button = QtWidgets.QPushButton('Save as')
167
- delete_button = QtWidgets.QPushButton('Delete records')
168
- add_button = QtWidgets.QPushButton('Add record')
169
- print_button = QtWidgets.QPushButton('Print')
170
-
171
- open_button.clicked.connect(self.load_csv)
172
- save_button.setShortcut(QtGui.QKeySequence.Open)
173
- save_button.clicked.connect(self.write_csv_update)
174
- save_button.setShortcut(QtGui.QKeySequence.Save)
175
- save_as_button.clicked.connect(self.write_csv)
176
- save_as_button.setShortcut(QtGui.QKeySequence.SaveAs)
177
- delete_button.clicked.connect(self.table_view_delete_records)
178
- delete_button.setShortcut(QtGui.QKeySequence.Delete)
179
-
180
- add_button.clicked.connect(self.table_view_add_records)
181
-
182
- self.last_files = QtWidgets.QComboBox()
183
- self.last_files.setFixedWidth(300)
184
- self.last_files.currentIndexChanged.connect(self.load_recent)
185
-
186
- self.line_find = QtWidgets.QLineEdit()
187
- self.line_find.setPlaceholderText("find")
188
- self.line_find.setClearButtonEnabled(True)
189
- self.line_find.setFixedWidth(250)
190
- self.line_find.returnPressed.connect(self.find_in_table)
191
-
192
- print_button.clicked.connect(self.handle_preview)
193
-
194
- self.project_btns.addWidget(open_button, QtWidgets.QDialogButtonBox.ActionRole)
195
- self.project_btns.addWidget(save_button, QtWidgets.QDialogButtonBox.ActionRole)
196
- self.project_btns.addWidget(save_as_button, QtWidgets.QDialogButtonBox.ActionRole)
197
- self.project_btns.addWidget(delete_button, QtWidgets.QDialogButtonBox.ActionRole)
198
- self.project_btns.addWidget(add_button, QtWidgets.QDialogButtonBox.ActionRole)
199
- self.project_btns.addWidget(self.line_find, QtWidgets.QDialogButtonBox.ActionRole)
200
- self.project_btns.addWidget(print_button, QtWidgets.QDialogButtonBox.ActionRole)
201
-
202
- # Add OK/cancel buttons
203
- self.ok_btn_box = QtWidgets.QDialogButtonBox()
204
- self.ok_btn_box.addButton("Run", QtWidgets.QDialogButtonBox.AcceptRole)
205
- self.ok_btn_box.addButton("Cancel", QtWidgets.QDialogButtonBox.RejectRole)
206
- self.ok_btn_box.addButton("Help", QtWidgets.QDialogButtonBox.HelpRole)
207
-
208
- self.ok_btn_box.accepted.connect(self.run)
209
- self.ok_btn_box.rejected.connect(self.reject)
210
- self.ok_btn_box.helpRequested.connect(self.help)
211
-
212
- hbox_btns = QtWidgets.QHBoxLayout()
213
- hbox_btns.addLayout(self.project_btns)
214
- hbox_btns.addWidget(self.ok_btn_box)
215
-
216
- vbox_main = QtWidgets.QVBoxLayout()
217
- vbox_main.addLayout(hbox_widgets)
218
- vbox_main.addLayout(hbox_btns)
219
- self.setLayout(vbox_main)
220
-
221
- # delete dialog when close
222
- self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
223
-
224
- self.setContentsMargins(10, 10, 10, 10)
225
- self.read_settings()
226
- self.table_view.setFocus()
227
- # self.statusBar().showMessage("Ready", 0)
228
-
229
- # signals
230
- self.tool_widgets.signal_save_tool_params.connect(self.table_view_update_record)
231
- self.signal_update_tool_widgets.connect(self.update_tool_widgets)
232
-
233
- def accept(self):
234
- if self.line_find.hasFocus():
235
- return
236
-
237
- print("Run the batch processing.")
238
- QtWidgets.QDialog.accept(self)
239
-
240
- def run(self):
241
- self.model.save_csv(self.filename)
242
- self.accept()
243
-
244
- def reject(self):
245
- print("Batch processing canceled.")
246
- self.close()
247
-
248
- def help(self):
249
- print("Help requested.")
250
-
251
- def table_view_clicked(self, item):
252
- print('Row, column:{}, {}'.format(item.row(), item.column()))
253
- self.signal_update_tool_widgets.emit(item.row())
254
-
255
- def table_view_vertical_header_clicked(self, item):
256
- print('Horizontal header clicked: {}'.format(item))
257
- self.signal_update_tool_widgets.emit(item)
258
-
259
- def table_view_key_up(self):
260
- current_row = self.table_view.selectionModel().selectedRows()[-1].row()
261
- if current_row >= 1:
262
- self.table_view.selectRow(current_row - 1)
263
- self.signal_update_tool_widgets.emit(current_row - 1)
264
-
265
- def table_view_delete_records(self):
266
- selected_index = self.table_view.selectionModel().selectedRows()
267
- rows = [item.row() for item in selected_index]
268
- rows.sort(reverse=True)
269
-
270
- for i in rows:
271
- self.model.removeRows(i)
272
-
273
- current_row = i
274
- if self.model.rowCount() > 0:
275
- if current_row > self.model.rowCount() - 1:
276
- current_row = self.model.rowCount() - 1
277
-
278
- self.table_view.selectRow(current_row)
279
- self.signal_update_tool_widgets.emit(current_row)
280
-
281
- print('remove row {}'.format(i))
282
-
283
- self.model.submit()
284
-
285
- def table_view_add_records(self):
286
- self.model.default_record = bt.get_bera_tool_parameters_list(self.tool_name)
287
- ret = self.model.insertRow(self.model.rowCount())
288
- if ret:
289
- count = self.model.rowCount() - 1
290
- self.table_view.selectRow(count)
291
- self.signal_update_tool_widgets.emit(count)
292
-
293
- print('Insert row in position {}'.format(count))
294
- self.model.submit()
295
-
296
- def table_view_update_record(self, row_data):
297
- current_row = self.table_view.selectionModel().selectedRows()[-1].row()
298
- self.model.updateRow(current_row, row_data)
299
-
300
- def update_tool_widgets(self, row):
301
- tool_params = self.model.data_row_dict(row)
302
- self.tool_widgets.update_widgets(tool_params)
303
- print('Update tool parameters for record {}'.format(tool_params))
304
-
305
- def table_view_key_down(self):
306
- current_row = self.table_view.selectionModel().selectedRows()[-1].row()
307
- if current_row < self.model.rowCount() - 1:
308
- self.table_view.selectRow(current_row + 1)
309
- self.signal_update_tool_widgets.emit(current_row + 1)
310
-
311
- def read_settings(self):
312
- print("reading settings")
313
- if self.settings.contains("geometry"):
314
- self.setGeometry(self.settings.value('geometry'))
315
- if self.settings.contains("recentFiles"):
316
- self.recent_files = self.settings.value('recentFiles')
317
- self.last_files.addItem("last Files")
318
- self.last_files.addItems(self.recent_files[:15])
319
-
320
- def save_settings(self):
321
- print("saving settings")
322
- self.settings.setValue('geometry', self.geometry())
323
- self.settings.setValue('recentFiles', self.recent_files)
324
-
325
- def closeEvent(self, event):
326
- print(self.model.setChanged)
327
- if self.model.setChanged:
328
- print("is changed, saving?")
329
- quit_msg = "<b>The document was changed.<br>Do you want to save the changes?</ b>"
330
- reply = QtWidgets.QMessageBox.question(
331
- self,
332
- "Save Confirmation",
333
- quit_msg,
334
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
335
- QtWidgets.QMessageBox.Yes,
336
- )
337
- if reply == QtWidgets.QMessageBox.Yes:
338
- self.write_csv_update()
339
- else:
340
- print("Settings not saved.")
341
- return
342
- else:
343
- print("nothing changed.")
344
- self.save_settings()
345
-
346
- def load_recent(self):
347
- if self.last_files.currentIndex() > 0:
348
- print(self.last_files.currentText())
349
- print(self.model.setChanged)
350
- if self.model.setChanged:
351
- print("is changed, saving?")
352
- quit_msg = "<b>The document was changed.<br>Save the changes?</ b>"
353
- reply = QtWidgets.QMessageBox.question(
354
- self,
355
- "Save Confirmation",
356
- quit_msg,
357
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
358
- QtWidgets.QMessageBox.Yes,
359
- )
360
- if reply == QtWidgets.QMessageBox.Yes:
361
- self.open_csv(self.last_files.currentText())
362
- else:
363
- self.open_csv(self.last_files.currentText())
364
- else:
365
- self.open_csv(self.last_files.currentText())
366
-
367
- def open_csv(self, path):
368
- f = open(path, 'r+b')
369
- with f:
370
- df = pd.read_csv(f, sep='\t|;|,|\s+', keep_default_na=False, engine='python',
371
- skipinitialspace=True, skip_blank_lines=True)
372
- f.close()
373
- self.filename = path
374
-
375
- self.model = _PandasModel(df)
376
- self.table_view.setModel(self.model)
377
- self.table_view.resizeColumnsToContents()
378
- self.table_view.selectRow(0)
379
- self.signal_update_tool_widgets.emit(0)
380
- # self.statusBar().showMessage("%s %s" % (path, "loaded"), 0)
381
-
382
- def find_in_table(self):
383
- self.table_view.clearSelection()
384
- text = self.line_find.text()
385
- model = self.table_view.model()
386
- for column in range(self.model.columnCount()):
387
- start = model.index(0, column)
388
- matches = model.match(
389
- start, QtCore.Qt.DisplayRole, text, -1, QtCore.Qt.MatchContains
390
- )
391
- if matches:
392
- for index in matches:
393
- self.table_view.selectionModel().select(
394
- index, QtCore.QItemSelectionModel.Select
395
- )
396
-
397
- def open_file(self, path=None):
398
- print(self.model.setChanged)
399
- if self.model.setChanged:
400
- print("is changed, saving?")
401
- quit_msg = "<b>The document was changed.<br>Save the changes?</ b>"
402
- reply = QtWidgets.QMessageBox.question(
403
- self,
404
- "Save Confirmation",
405
- quit_msg,
406
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
407
- QtWidgets.QMessageBox.Yes,
408
- )
409
- if reply == QtWidgets.QMessageBox.Yes:
410
- self.write_csv_update()
411
- else:
412
- print("not saved, loading ...")
413
- return
414
- path, _ = QtWidgets.QFileDialog.getOpenFileName(
415
- self,
416
- "Open File",
417
- QtCore.QDir.homePath() + "/Document/CSV/",
418
- "CSV Files (*.csv)",
419
- )
420
- if path:
421
- return path
422
-
423
- def load_csv(self):
424
- file_name = self.open_file()
425
- if file_name:
426
- print(file_name + " loaded")
427
- f = open(file_name, 'r+b')
428
- with f:
429
- df = pd.read_csv(
430
- f,
431
- sep="\t|;|,|\s+",
432
- keep_default_na=False,
433
- engine="python",
434
- skipinitialspace=True,
435
- skip_blank_lines=True,
436
- )
437
- f.close()
438
- self.model = _PandasModel(df)
439
- self.table_view.setModel(self.model)
440
- self.table_view.resizeColumnsToContents()
441
- self.table_view.selectRow(0)
442
- # self.statusBar().showMessage("%s %s" % (fileName, "loaded"), 0)
443
- self.recent_files.insert(0, file_name)
444
- self.last_files.insertItem(1, file_name)
445
-
446
- def write_csv(self):
447
- file_name, _ = QtWidgets.QFileDialog.getSaveFileName(
448
- self, "Open File", self.filename, "CSV Files (*.csv)"
449
- )
450
-
451
- if file_name:
452
- print(file_name + " saved")
453
- f = open(file_name, 'w')
454
- new_model = self.model
455
- data_frame = new_model._df.copy()
456
- data_frame.to_csv(f, sep=',', index=False, header=True, lineterminator='\n')
457
-
458
- def write_csv_update(self):
459
- if self.filename:
460
- f = open(self.filename, 'w')
461
- new_model = self.model
462
- data_frame = new_model._df.copy()
463
- data_frame.to_csv(f, sep='\t', index=False, header=False)
464
- self.model.setChanged = False
465
- print("%s %s" % (self.filename, "saved"))
466
- # self.statusBar().showMessage("%s %s" % (self.filename, "saved"), 0)
467
-
468
- def handle_preview(self):
469
- if self.model.rowCount() == 0:
470
- self.msg("no rows")
471
- else:
472
- dialog = QtPrintSupport.QPrintPreviewDialog()
473
- dialog.setFixedSize(1000, 700)
474
- dialog.paintRequested.connect(self.handle_paint_request)
475
- dialog.exec_()
476
- print("Print Preview closed")
477
-
478
- def handle_paint_request(self, printer):
479
- printer.setDocName(self.filename)
480
- document = QtGui.QTextDocument()
481
- cursor = QtGui.QTextCursor(document)
482
- model = self.table_view.model()
483
- table_format = QtGui.QTextTableFormat()
484
- table_format.setBorder(0.2)
485
- table_format.setBorderStyle(3)
486
- table_format.setCellSpacing(0)
487
- table_format.setTopMargin(0)
488
- table_format.setCellPadding(4)
489
- model = self.table_view.model()
490
-
491
- # get headers
492
- my_header = []
493
- for i in range(0, model.columnCount()):
494
- my_header = model.headerData(i, QtCore.Qt.Horizontal)
495
- cursor.insertText(str(my_header))
496
- cursor.movePosition(QtGui.QTextCursor.NextCell)
497
- # get cells
498
- for row in range(0, model.rowCount()):
499
- for col in range(0, model.columnCount()):
500
- index = model.index(row, col)
501
- cursor.insertText(str(index.data()))
502
- cursor.movePosition(QtGui.QTextCursor.NextCell)
503
- document.print_(printer)
504
-
505
-
506
- if __name__ == "__main__":
507
- app = QtCore.QApplication(sys.argv)
508
- main = BPDialog('Raster Line Attributes')
509
- main.show()
510
- if len(sys.argv) > 1:
511
- main.open_csv(sys.argv[1])
512
-
513
- sys.exit(app.exec_())
@@ -1,162 +0,0 @@
1
- import os
2
- import sys
3
-
4
- os.environ["QT_API"] = "pyqt5"
5
- from pyqtlet2 import L, MapWidget
6
- from qtpy.QtCore import Qt, Signal
7
- from qtpy.QtWidgets import (
8
- QApplication,
9
- QDialog,
10
- QDialogButtonBox,
11
- QGroupBox,
12
- QHBoxLayout,
13
- QTreeWidget,
14
- QTreeWidgetItem,
15
- QVBoxLayout,
16
- QWidget,
17
- )
18
-
19
-
20
- class MapWindow(QDialog):
21
- def __init__(self, parent=None):
22
- # Setting up the widgets and layout
23
- super(MapWindow, self).__init__(parent)
24
- self.setWindowTitle("Tiler map")
25
- self.setGeometry(0, 0, 1200, 800)
26
-
27
- # delete dialog when close
28
- self.setAttribute(Qt.WA_DeleteOnClose)
29
-
30
- # Add OK/cancel buttons
31
- self.ok_btn_box = QDialogButtonBox(Qt.Vertical)
32
- self.ok_btn_box.addButton("Run Tiler", QDialogButtonBox.AcceptRole)
33
- self.ok_btn_box.addButton("Cancel", QDialogButtonBox.RejectRole)
34
- self.ok_btn_box.addButton("Help", QDialogButtonBox.HelpRole)
35
-
36
- self.ok_btn_box.buttons()[0].setFixedSize(120, 40)
37
- self.ok_btn_box.buttons()[1].setFixedSize(120, 40)
38
- self.ok_btn_box.buttons()[2].setFixedSize(120, 40)
39
-
40
- self.ok_btn_box.accepted.connect(self.run)
41
- self.ok_btn_box.rejected.connect(self.cancel)
42
- self.ok_btn_box.helpRequested.connect(self.help)
43
-
44
- self.info_layout = QVBoxLayout() # layout reserved for tiles info widgets
45
- self.vbox_group = QVBoxLayout()
46
- self.vbox_group.addLayout(self.info_layout)
47
- self.vbox_group.addStretch()
48
- self.vbox_group.addWidget(self.ok_btn_box, alignment=Qt.AlignCenter)
49
-
50
- groupbox_info = QGroupBox("Tiles")
51
- groupbox_info.setLayout(self.vbox_group)
52
-
53
- central_widget = QWidget()
54
- map_layout = QHBoxLayout(central_widget)
55
- map_layout.addWidget(groupbox_info)
56
-
57
- groupbox_map = QGroupBox("Map")
58
- self.map_widget = MapWidget()
59
- self.map_widget.setContentsMargins(10, 10, 10, 10)
60
- self.vbox_map = QVBoxLayout()
61
- self.vbox_map.addWidget(self.map_widget)
62
- groupbox_map.setLayout(self.vbox_map)
63
- map_layout.addWidget(groupbox_map, 10)
64
- self.setLayout(map_layout)
65
-
66
- # Working with the maps with pyqtlet
67
- self.map = L.map(self.map_widget)
68
- self.map.setView([0, 0], 10) # this is necessary
69
-
70
- L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png").addTo(self.map)
71
-
72
- # add marker layer
73
- # self.add_marker_layer()
74
- self.show()
75
-
76
- def add_polygons_to_map(self, layer_name, polygons, color):
77
- style = {"fillOpacity": 0.1, "color": color}
78
- vars()[layer_name] = L.polygon(polygons, style)
79
- self.map.addLayer(vars()[layer_name])
80
-
81
- # this works too. addLayer has to be called first
82
- # self.map.runJavaScript("var stylePoly = {fillColor:'red',color: 'blue',weight:2,fillOpacity:0.8};", 0)
83
- # self.map.runJavaScript(f'{self.multipolygon.jsName}.setStyle(stylePoly);', 0)
84
-
85
- def add_polylines_to_map(self, polylines, color):
86
- style = {"color": color}
87
- lines = L.polyline(polylines, style)
88
- self.map.addLayer(lines)
89
-
90
- def set_view(self, point, zoom):
91
- self.map = self.map.setView(point, zoom)
92
-
93
- # bounds is a pair of corner points, LL and UR
94
- def fit_bounds(self, bounds):
95
- # self.map.fitBounds(bounds)
96
- self.map.runJavaScript(f"{self.map.jsName}.fitBounds(bounds);", 0)
97
-
98
- def add_marker_layer(self):
99
- self.marker = L.marker([12.934056, -77.610029])
100
- self.marker.bindPopup("Maps are a treasure.")
101
- self.map.addLayer(self.marker)
102
-
103
- # Create a icon called markerIcon in the js runtime.
104
- self.map.runJavaScript(
105
- "var markerIcon "
106
- '= L.icon({iconUrl: "https://leafletjs.com/examples/custom-icons/leaf-red.png"});',
107
- 0,
108
- )
109
-
110
- # Edit the existing python object by accessing it's jsName property
111
- self.map.runJavaScript(f"{self.marker.jsName}.setIcon(markerIcon);", 0)
112
-
113
- def accept(self):
114
- print("Run the tiling.")
115
- QDialog.accept(self)
116
-
117
- def run(self):
118
- self.accept()
119
-
120
- def cancel(self):
121
- print("Tiling canceled.")
122
- self.reject()
123
-
124
- def help(self):
125
- print("Help requested.")
126
-
127
- def set_tiles_info(self, tiles_info):
128
- tree = QTreeWidget()
129
- tree.setColumnCount(2)
130
- tree.setHeaderLabels(["Item", "Value"])
131
- item = QTreeWidgetItem(["Tiles"])
132
- for key, value in tiles_info.items():
133
- child = QTreeWidgetItem([key, str(value)])
134
- item.addChild(child)
135
-
136
- tree.insertTopLevelItem(0, item)
137
- tree.expandAll()
138
-
139
- # add to group widget
140
- self.vbox_group.insertWidget(0, tree)
141
-
142
-
143
- if __name__ == "__main__":
144
- # supress web engine logging
145
- os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--enable-logging --log-level=3"
146
-
147
- app = QApplication(sys.argv)
148
- widget = MapWindow()
149
-
150
- # add polygons to map
151
- polygon_coords_base = [
152
- [[17.285044, 78.286671], [16.606174, 80.748015], [17.886816, 83.518482]]
153
- ]
154
- widget.add_polygons_to_map(polygon_coords_base, "blue")
155
-
156
- polygon_coords = [
157
- [[17.385044, 78.486671], [16.506174, 80.648015], [17.686816, 83.218482]],
158
- [[13.082680, 80.270718], [12.971599, 77.594563], [15.828126, 78.037279]],
159
- ]
160
- widget.add_polygons_to_map(polygon_coords, "red")
161
-
162
- sys.exit(app.exec_())