BERATools 0.2.0__py3-none-any.whl → 0.2.2__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.
- beratools/__init__.py +1 -7
- beratools/core/algo_centerline.py +491 -351
- beratools/core/algo_common.py +497 -0
- beratools/core/algo_cost.py +192 -0
- beratools/core/{dijkstra_algorithm.py → algo_dijkstra.py} +503 -460
- beratools/core/algo_footprint_rel.py +577 -0
- beratools/core/algo_line_grouping.py +944 -0
- beratools/core/algo_merge_lines.py +214 -0
- beratools/core/algo_split_with_lines.py +304 -0
- beratools/core/algo_tiler.py +428 -0
- beratools/core/algo_vertex_optimization.py +469 -0
- beratools/core/constants.py +52 -86
- beratools/core/logger.py +76 -85
- beratools/core/tool_base.py +196 -133
- beratools/gui/__init__.py +11 -15
- beratools/gui/{beratools.json → assets/beratools.json} +2185 -2300
- beratools/gui/batch_processing_dlg.py +513 -463
- beratools/gui/bt_data.py +481 -487
- beratools/gui/bt_gui_main.py +710 -691
- beratools/gui/main.py +26 -0
- beratools/gui/map_window.py +162 -146
- beratools/gui/tool_widgets.py +725 -493
- beratools/tools/Beratools_r_script.r +1120 -1120
- beratools/tools/Ht_metrics.py +116 -116
- beratools/tools/__init__.py +7 -7
- beratools/tools/batch_processing.py +136 -132
- beratools/tools/canopy_threshold_relative.py +672 -670
- beratools/tools/canopycostraster.py +222 -222
- beratools/tools/centerline.py +136 -176
- beratools/tools/common.py +857 -885
- beratools/tools/fl_regen_csf.py +428 -428
- beratools/tools/forest_line_attributes.py +408 -408
- beratools/tools/line_footprint_absolute.py +213 -363
- beratools/tools/line_footprint_fixed.py +436 -282
- beratools/tools/line_footprint_functions.py +733 -720
- beratools/tools/line_footprint_relative.py +73 -64
- beratools/tools/line_grouping.py +45 -0
- beratools/tools/ln_relative_metrics.py +615 -615
- beratools/tools/r_cal_lpi_elai.r +24 -24
- beratools/tools/r_generate_pd_focalraster.r +100 -100
- beratools/tools/r_interface.py +79 -79
- beratools/tools/r_point_density.r +8 -8
- beratools/tools/rpy_chm2trees.py +86 -86
- beratools/tools/rpy_dsm_chm_by.py +81 -81
- beratools/tools/rpy_dtm_by.py +63 -63
- beratools/tools/rpy_find_cellsize.py +43 -43
- beratools/tools/rpy_gnd_csf.py +74 -74
- beratools/tools/rpy_hummock_hollow.py +85 -85
- beratools/tools/rpy_hummock_hollow_raster.py +71 -71
- beratools/tools/rpy_las_info.py +51 -51
- beratools/tools/rpy_laz2las.py +40 -40
- beratools/tools/rpy_lpi_elai_lascat.py +466 -466
- beratools/tools/rpy_normalized_lidar_by.py +56 -56
- beratools/tools/rpy_percent_above_dbh.py +80 -80
- beratools/tools/rpy_points2trees.py +88 -88
- beratools/tools/rpy_vegcoverage.py +94 -94
- beratools/tools/tiler.py +48 -206
- beratools/tools/tool_template.py +69 -54
- beratools/tools/vertex_optimization.py +61 -620
- beratools/tools/zonal_threshold.py +144 -144
- beratools-0.2.2.dist-info/METADATA +108 -0
- beratools-0.2.2.dist-info/RECORD +74 -0
- {beratools-0.2.0.dist-info → beratools-0.2.2.dist-info}/WHEEL +1 -1
- {beratools-0.2.0.dist-info → beratools-0.2.2.dist-info}/licenses/LICENSE +22 -22
- beratools/gui/cli.py +0 -18
- beratools/gui/gui.json +0 -8
- beratools/gui_tk/ASCII Banners.txt +0 -248
- beratools/gui_tk/__init__.py +0 -20
- beratools/gui_tk/beratools_main.py +0 -515
- beratools/gui_tk/bt_widgets.py +0 -442
- beratools/gui_tk/cli.py +0 -18
- beratools/gui_tk/img/BERALogo.png +0 -0
- beratools/gui_tk/img/closed.gif +0 -0
- beratools/gui_tk/img/closed.png +0 -0
- beratools/gui_tk/img/open.gif +0 -0
- beratools/gui_tk/img/open.png +0 -0
- beratools/gui_tk/img/tool.gif +0 -0
- beratools/gui_tk/img/tool.png +0 -0
- beratools/gui_tk/main.py +0 -14
- beratools/gui_tk/map_window.py +0 -144
- beratools/gui_tk/runner.py +0 -1481
- beratools/gui_tk/tooltip.py +0 -55
- beratools/third_party/pyqtlet2/__init__.py +0 -9
- beratools/third_party/pyqtlet2/leaflet/__init__.py +0 -26
- beratools/third_party/pyqtlet2/leaflet/control/__init__.py +0 -6
- beratools/third_party/pyqtlet2/leaflet/control/control.py +0 -59
- beratools/third_party/pyqtlet2/leaflet/control/draw.py +0 -52
- beratools/third_party/pyqtlet2/leaflet/control/layers.py +0 -20
- beratools/third_party/pyqtlet2/leaflet/core/Parser.py +0 -24
- beratools/third_party/pyqtlet2/leaflet/core/__init__.py +0 -2
- beratools/third_party/pyqtlet2/leaflet/core/evented.py +0 -180
- beratools/third_party/pyqtlet2/leaflet/layer/__init__.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/featuregroup.py +0 -34
- beratools/third_party/pyqtlet2/leaflet/layer/icon/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/layer/icon/icon.py +0 -30
- beratools/third_party/pyqtlet2/leaflet/layer/imageoverlay.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/layer.py +0 -105
- beratools/third_party/pyqtlet2/leaflet/layer/layergroup.py +0 -45
- beratools/third_party/pyqtlet2/leaflet/layer/marker/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/layer/marker/marker.py +0 -91
- beratools/third_party/pyqtlet2/leaflet/layer/tile/__init__.py +0 -2
- beratools/third_party/pyqtlet2/leaflet/layer/tile/gridlayer.py +0 -4
- beratools/third_party/pyqtlet2/leaflet/layer/tile/tilelayer.py +0 -16
- beratools/third_party/pyqtlet2/leaflet/layer/vector/__init__.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circle.py +0 -15
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circlemarker.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/vector/path.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polygon.py +0 -14
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polyline.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/vector/rectangle.py +0 -14
- beratools/third_party/pyqtlet2/leaflet/map/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/map/map.py +0 -220
- beratools/third_party/pyqtlet2/mapwidget.py +0 -45
- beratools/third_party/pyqtlet2/web/custom.js +0 -43
- beratools/third_party/pyqtlet2/web/map.html +0 -23
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.css +0 -656
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.js +0 -6
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.codeclimate.yml +0 -14
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.editorconfig +0 -4
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.gitattributes +0 -22
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.travis.yml +0 -43
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/LICENSE +0 -20
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.svg +0 -156
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.css +0 -10
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.js +0 -10
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/LICENSE +0 -22
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/leaflet.rotatedMarker.js +0 -57
- beratools/tools/forest_line_ecosite.py +0 -216
- beratools/tools/lapis_all.py +0 -103
- beratools/tools/least_cost_path_from_chm.py +0 -152
- beratools-0.2.0.dist-info/METADATA +0 -63
- beratools-0.2.0.dist-info/RECORD +0 -142
- /beratools/gui/{img → assets}/BERALogo.png +0 -0
- /beratools/gui/{img → assets}/closed.gif +0 -0
- /beratools/gui/{img → assets}/closed.png +0 -0
- /beratools/{gui_tk → gui/assets}/gui.json +0 -0
- /beratools/gui/{img → assets}/open.gif +0 -0
- /beratools/gui/{img → assets}/open.png +0 -0
- /beratools/gui/{img → assets}/tool.gif +0 -0
- /beratools/gui/{img → assets}/tool.png +0 -0
- {beratools-0.2.0.dist-info → beratools-0.2.2.dist-info}/entry_points.txt +0 -0
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from .layer import Layer
|
|
2
|
-
|
|
3
|
-
class LayerGroup(Layer):
|
|
4
|
-
"""
|
|
5
|
-
Used to group several layers and handle them as one. If you add it to the map, any layers added or removed from the group will be added/removed on the map as well.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
@property
|
|
9
|
-
def layers(self):
|
|
10
|
-
return self._layers
|
|
11
|
-
|
|
12
|
-
def __init__(self):
|
|
13
|
-
super().__init__()
|
|
14
|
-
self._layers = []
|
|
15
|
-
if self._map:
|
|
16
|
-
self._initJs()
|
|
17
|
-
|
|
18
|
-
def _initJs(self):
|
|
19
|
-
leafletJsObject = 'new L.layerGroup()'
|
|
20
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
21
|
-
|
|
22
|
-
def addLayer(self, layer):
|
|
23
|
-
self._layers.append(layer)
|
|
24
|
-
layer.map = self._map
|
|
25
|
-
layer._initJs()
|
|
26
|
-
js = '{layerGroup}.addLayer({layerName})'.format(layerGroup=self._layerName,
|
|
27
|
-
layerName=layer._layerName)
|
|
28
|
-
self.runJavaScriptForMapIndex(js)
|
|
29
|
-
|
|
30
|
-
def removeLayer(self, layer):
|
|
31
|
-
if not layer in self._layers:
|
|
32
|
-
# TODO Raise ValueError?
|
|
33
|
-
return
|
|
34
|
-
self._layers.remove(layer)
|
|
35
|
-
js = '{layerGroup}.removeLayer({layerName})'.format(layerGroup=self._layerName,
|
|
36
|
-
layerName=layer._layerName)
|
|
37
|
-
self.runJavaScriptForMapIndex(js)
|
|
38
|
-
|
|
39
|
-
def clearLayers(self):
|
|
40
|
-
js = '{layerGroup}.clearLayers()'.format(layerGroup=self._layerName)
|
|
41
|
-
self.runJavaScriptForMapIndex(js)
|
|
42
|
-
|
|
43
|
-
def toGeoJSON(self, callback):
|
|
44
|
-
self.getJsResponseForMapIndex(f'{self.jsName}.toGeoJSON()', callback)
|
|
45
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .marker import Marker
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
from ..layer import Layer
|
|
2
|
-
from ..icon import Icon
|
|
3
|
-
from ...core.Parser import Parser
|
|
4
|
-
|
|
5
|
-
from qtpy.QtCore import Slot, Signal, QJsonValue
|
|
6
|
-
|
|
7
|
-
from typing import List
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Marker(Layer):
|
|
11
|
-
moveend = Signal(dict)
|
|
12
|
-
move = Signal(dict)
|
|
13
|
-
click = Signal(dict)
|
|
14
|
-
|
|
15
|
-
def __init__(self, latLng: List[float], options=None):
|
|
16
|
-
super().__init__()
|
|
17
|
-
if isinstance(options, type(None)):
|
|
18
|
-
options = {}
|
|
19
|
-
self.latLng = latLng
|
|
20
|
-
self.options = options
|
|
21
|
-
self.opacity = options.get('opacity', 1)
|
|
22
|
-
self.draggable = options.get('draggable', False)
|
|
23
|
-
if self._map:
|
|
24
|
-
self._initJs()
|
|
25
|
-
|
|
26
|
-
@Slot(QJsonValue)
|
|
27
|
-
def _onMove(self, event):
|
|
28
|
-
self._logger.debug('marker moved. event: {event}'.format(event=event))
|
|
29
|
-
event = self._qJsonValueToDict(event)
|
|
30
|
-
self.latLng = [event["latlng"]["lat"], event["latlng"]["lng"]]
|
|
31
|
-
self.move.emit({**self._qJsonValueToDict(event), "latLng": self.latLng, "sender": self})
|
|
32
|
-
|
|
33
|
-
@Slot(QJsonValue)
|
|
34
|
-
def _onMoveend(self, event):
|
|
35
|
-
self._logger.debug('marker moved. event: {event}'.format(event=event))
|
|
36
|
-
if self.opacity == 0:
|
|
37
|
-
return
|
|
38
|
-
self.moveend.emit({**self._qJsonValueToDict(event), "latLng": self.latLng, "sender": self})
|
|
39
|
-
|
|
40
|
-
@Slot(QJsonValue)
|
|
41
|
-
def _click(self, event):
|
|
42
|
-
self._logger.debug('marker clicked. event: {event}'.format(event=event))
|
|
43
|
-
if self.opacity == 0:
|
|
44
|
-
return
|
|
45
|
-
self.click.emit({**self._qJsonValueToDict(event), "sender": self})
|
|
46
|
-
|
|
47
|
-
def _initJs(self):
|
|
48
|
-
leafletJsObject = 'L.marker({latLng}'.format(latLng=self.latLng)
|
|
49
|
-
if self.options:
|
|
50
|
-
leafletJsObject += ', {options}'.format(options=Parser.dict_for_js(self.options))
|
|
51
|
-
leafletJsObject += ')'
|
|
52
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
53
|
-
self._connectEventToSignal('move', '_onMove', self._map.mapWidgetIndex)
|
|
54
|
-
self._connectEventToSignal('moveend', '_onMoveend', self._map.mapWidgetIndex)
|
|
55
|
-
self._connectEventToSignal('click', '_click', self._map.mapWidgetIndex)
|
|
56
|
-
|
|
57
|
-
def setLatLng(self, latLng):
|
|
58
|
-
self.latLng = latLng
|
|
59
|
-
js = '{layerName}.setLatLng({latLng})'.format(
|
|
60
|
-
layerName=self._layerName, latLng=latLng)
|
|
61
|
-
self.runJavaScriptForMapIndex(js)
|
|
62
|
-
return self
|
|
63
|
-
|
|
64
|
-
def setOpacity(self, opacity):
|
|
65
|
-
self.opacity = opacity
|
|
66
|
-
js = '{layerName}.setOpacity({opacity})'.format(
|
|
67
|
-
layerName=self._layerName, opacity=self.opacity)
|
|
68
|
-
self.runJavaScriptForMapIndex(js)
|
|
69
|
-
return self
|
|
70
|
-
|
|
71
|
-
def setDragging(self, draggable):
|
|
72
|
-
self.draggable = draggable
|
|
73
|
-
option = 'enable' if self.draggable else 'disable'
|
|
74
|
-
js = '{layerName}.dragging.{option}();'.format(layerName=self._layerName, option=option)
|
|
75
|
-
self.runJavaScriptForMapIndex(js)
|
|
76
|
-
return self
|
|
77
|
-
|
|
78
|
-
def setIcon(self, icon: Icon):
|
|
79
|
-
js = '{layerName}.setIcon({markerIcon});'.format(layerName=self._layerName, markerIcon=icon._layerName)
|
|
80
|
-
self.runJavaScriptForMapIndex(js)
|
|
81
|
-
return self
|
|
82
|
-
|
|
83
|
-
def setRotationAngle(self, angle_deg: float):
|
|
84
|
-
js = '{layerName}.setRotationAngle({angle_deg});'.format(layerName=self._layerName, angle_deg=angle_deg)
|
|
85
|
-
self.runJavaScriptForMapIndex(js)
|
|
86
|
-
return self
|
|
87
|
-
|
|
88
|
-
def setRotationOrigin(self, origin: str):
|
|
89
|
-
js = '{layerName}.setRotationOrigin({origin});'.format(layerName=self._layerName, origin=origin)
|
|
90
|
-
self.runJavaScriptForMapIndex(js)
|
|
91
|
-
return self
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from . import GridLayer
|
|
2
|
-
|
|
3
|
-
class TileLayer(GridLayer):
|
|
4
|
-
def __init__(self, urlTemplate, options=None):
|
|
5
|
-
super().__init__()
|
|
6
|
-
self.urlTemplate = urlTemplate
|
|
7
|
-
self.options = options
|
|
8
|
-
if self._map:
|
|
9
|
-
self._initJs()
|
|
10
|
-
|
|
11
|
-
def _initJs(self):
|
|
12
|
-
leafletJsObject = 'L.tileLayer("{urlTemplate}"'.format(urlTemplate=self.urlTemplate)
|
|
13
|
-
if self.options:
|
|
14
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
15
|
-
leafletJsObject += ')'
|
|
16
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from .circlemarker import CircleMarker
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Circle(CircleMarker):
|
|
5
|
-
def __init__(self, latLng, radius, options=None):
|
|
6
|
-
self.radius = radius
|
|
7
|
-
super().__init__(latLng, options)
|
|
8
|
-
|
|
9
|
-
def _initJs(self):
|
|
10
|
-
leafletJsObject = 'L.circle({latLng},{radius}'.format(latLng=self.latLng,
|
|
11
|
-
radius=self.radius)
|
|
12
|
-
if self.options:
|
|
13
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
14
|
-
leafletJsObject += ')'
|
|
15
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from .path import Path
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class CircleMarker(Path):
|
|
5
|
-
def __init__(self, latLng, options=None):
|
|
6
|
-
super().__init__()
|
|
7
|
-
self.latLng = latLng
|
|
8
|
-
self.options = options
|
|
9
|
-
if self._map:
|
|
10
|
-
self._initJs()
|
|
11
|
-
|
|
12
|
-
def _initJs(self):
|
|
13
|
-
leafletJsObject = 'L.circleMarker({latLng}'.format(latLng=self.latLng)
|
|
14
|
-
if self.options:
|
|
15
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
16
|
-
leafletJsObject += ')'
|
|
17
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
18
|
-
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from .polyline import Polyline
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Polygon(Polyline):
|
|
5
|
-
def __init__(self, latLngs, options=None):
|
|
6
|
-
super().__init__(latLngs, options)
|
|
7
|
-
|
|
8
|
-
def _initJs(self):
|
|
9
|
-
leafletJsObject = 'L.polygon({latLngs}'.format(latLngs=self.latLngs)
|
|
10
|
-
if self.options:
|
|
11
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
12
|
-
leafletJsObject += ')'
|
|
13
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
14
|
-
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from .path import Path
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Polyline(Path):
|
|
5
|
-
def __init__(self, latLngs, options=None):
|
|
6
|
-
super().__init__()
|
|
7
|
-
self.latLngs = latLngs
|
|
8
|
-
self.options = options
|
|
9
|
-
if self._map:
|
|
10
|
-
self._initJs()
|
|
11
|
-
|
|
12
|
-
def _initJs(self):
|
|
13
|
-
leafletJsObject = 'L.polyline({latLngs}'.format(latLngs=self.latLngs)
|
|
14
|
-
if self.options:
|
|
15
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
16
|
-
leafletJsObject += ')'
|
|
17
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
18
|
-
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from .polygon import Polygon
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Rectangle(Polygon):
|
|
5
|
-
def __init__(self, latLngs, options=None):
|
|
6
|
-
super().__init__(latLngs, options)
|
|
7
|
-
|
|
8
|
-
def _initJs(self):
|
|
9
|
-
leafletJsObject = 'L.rectangle({latLngs}'.format(latLngs=self.latLngs)
|
|
10
|
-
if self.options:
|
|
11
|
-
leafletJsObject += ', {options}'.format(options=self.options)
|
|
12
|
-
leafletJsObject += ')'
|
|
13
|
-
self._createJsObject(leafletJsObject, self._map.mapWidgetIndex)
|
|
14
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .map import Map
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
import time
|
|
5
|
-
|
|
6
|
-
from qtpy.QtCore import Slot, Signal, QJsonValue
|
|
7
|
-
|
|
8
|
-
from ... import mapwidget
|
|
9
|
-
from ..core import Evented
|
|
10
|
-
from ..layer import Layer
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Map(Evented):
|
|
14
|
-
'''
|
|
15
|
-
.. module:: pyqtlet2
|
|
16
|
-
|
|
17
|
-
pyqtlet2 equivalent of L.map
|
|
18
|
-
|
|
19
|
-
Map element has to be the first pyqtlet2 object to be initiated.
|
|
20
|
-
|
|
21
|
-
.. note::
|
|
22
|
-
Further documentation can be found at the official leaflet API.
|
|
23
|
-
|
|
24
|
-
:param pyqtlet2.MapWidget mapWidget: The mapwidget object
|
|
25
|
-
Should only be sent once, when the first object is being
|
|
26
|
-
initialised.
|
|
27
|
-
|
|
28
|
-
:param dict options: Options for initiation (optional)
|
|
29
|
-
'''
|
|
30
|
-
|
|
31
|
-
clicked = Signal(dict)
|
|
32
|
-
zoom = Signal(dict)
|
|
33
|
-
drawCreated = Signal(dict)
|
|
34
|
-
right_mouse_clicked = Signal(dict)
|
|
35
|
-
mapWidgetCounter = 0
|
|
36
|
-
|
|
37
|
-
@property
|
|
38
|
-
def layers(self):
|
|
39
|
-
"""
|
|
40
|
-
Instead of L.map.eachLayer
|
|
41
|
-
"""
|
|
42
|
-
return self._layers
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def jsName(self):
|
|
46
|
-
'''
|
|
47
|
-
Name of the Leaflet element
|
|
48
|
-
'''
|
|
49
|
-
return self._jsName
|
|
50
|
-
|
|
51
|
-
@Slot(QJsonValue)
|
|
52
|
-
def _onClick(self, event):
|
|
53
|
-
self._logger.debug('map clicked. event: {event}'.format(event=event))
|
|
54
|
-
self.clicked.emit(self._qJsonValueToDict(event))
|
|
55
|
-
|
|
56
|
-
@Slot(QJsonValue)
|
|
57
|
-
def _onRightClick(self, event):
|
|
58
|
-
self._logger.debug('map clicked. event: {event}'.format(event=event))
|
|
59
|
-
self.right_mouse_clicked.emit(self._qJsonValueToDict(event))
|
|
60
|
-
|
|
61
|
-
@Slot(QJsonValue)
|
|
62
|
-
def _onDrawCreated(self, event):
|
|
63
|
-
self._logger.debug('draw created. event: {event}'.format(event=event))
|
|
64
|
-
self.drawCreated.emit(self._qJsonValueToDict(event))
|
|
65
|
-
|
|
66
|
-
@Slot(QJsonValue)
|
|
67
|
-
def _onZoom(self, event):
|
|
68
|
-
self._logger.debug('map zoom. event: {event}'.format(event=event))
|
|
69
|
-
self.zoom.emit(self._qJsonValueToDict(event))
|
|
70
|
-
|
|
71
|
-
def __init__(self, mapWidget, options=None):
|
|
72
|
-
'''
|
|
73
|
-
pyqtlet2 equivalent of L.map
|
|
74
|
-
|
|
75
|
-
Map element has to be the first pyqtlet2 object to be initiated.
|
|
76
|
-
|
|
77
|
-
:param pyqtlet2.MapWidget mapWidget: The mapwidget object
|
|
78
|
-
Should only be sent once, when the first object is being
|
|
79
|
-
initialised.
|
|
80
|
-
|
|
81
|
-
:param dict options: Options for initiation (optional)
|
|
82
|
-
|
|
83
|
-
.. note
|
|
84
|
-
Further documentation can be found at the official leaflet API.
|
|
85
|
-
'''
|
|
86
|
-
|
|
87
|
-
super().__init__(mapWidget, Map.mapWidgetCounter)
|
|
88
|
-
self.mapWidgetIndex = Map.mapWidgetCounter
|
|
89
|
-
Map.mapWidgetCounter += 1
|
|
90
|
-
self._logger = logging.getLogger(__name__)
|
|
91
|
-
self.options = options
|
|
92
|
-
self._layers = []
|
|
93
|
-
self._controls = []
|
|
94
|
-
self._jsName = 'map'
|
|
95
|
-
self._initJs()
|
|
96
|
-
self._connectEventToSignal('click', '_onClick', self.mapWidgetIndex)
|
|
97
|
-
self._connectEventToSignal('contextmenu', '_onRightClick', self.mapWidgetIndex)
|
|
98
|
-
self._connectEventToSignal('zoom', '_onZoom', self.mapWidgetIndex)
|
|
99
|
-
self._connectEventToSignal('draw:created', '_onDrawCreated', self.mapWidgetIndex)
|
|
100
|
-
|
|
101
|
-
def _initJs(self):
|
|
102
|
-
jsObject = 'L.map("map"'
|
|
103
|
-
if self.options:
|
|
104
|
-
jsObject += ', {options}'.format(options=self._stringifyForJs(self.options))
|
|
105
|
-
jsObject += ')'
|
|
106
|
-
self._createJsObject(jsObject, self.mapWidgetIndex)
|
|
107
|
-
|
|
108
|
-
def setView(self, latLng, zoom=None, options=None):
|
|
109
|
-
js = 'map.setView({latLng}'.format(latLng=latLng)
|
|
110
|
-
if zoom:
|
|
111
|
-
js += ', {zoom}'.format(zoom=zoom)
|
|
112
|
-
if options:
|
|
113
|
-
js += ', {options}'.format(options=options)
|
|
114
|
-
js += ');'
|
|
115
|
-
self.runJavaScript(js, self.mapWidgetIndex)
|
|
116
|
-
return self
|
|
117
|
-
|
|
118
|
-
def runJavaScriptForMap(self, js):
|
|
119
|
-
self.runJavaScript(js, self.mapWidgetIndex)
|
|
120
|
-
|
|
121
|
-
def addLayer(self, layer: Layer):
|
|
122
|
-
self._layers.append(layer)
|
|
123
|
-
layer.map = self
|
|
124
|
-
layer._initJs()
|
|
125
|
-
js = 'map.addLayer({layerName})'.format(layerName=layer.layerName)
|
|
126
|
-
self.runJavaScriptForMap(js)
|
|
127
|
-
layer._initPopupAndTooltip()
|
|
128
|
-
return self
|
|
129
|
-
|
|
130
|
-
def removeLayer(self, layer):
|
|
131
|
-
if layer not in self._layers:
|
|
132
|
-
# TODO Should we raise a ValueError here? Or just return
|
|
133
|
-
return
|
|
134
|
-
self._layers.remove(layer)
|
|
135
|
-
layer.map = None
|
|
136
|
-
js = 'map.removeLayer({layerName})'.format(layerName=layer.layerName)
|
|
137
|
-
self.runJavaScriptForMap(js)
|
|
138
|
-
return self
|
|
139
|
-
|
|
140
|
-
def addControl(self, control):
|
|
141
|
-
self._controls.append(control)
|
|
142
|
-
control.map = self
|
|
143
|
-
control._initJs()
|
|
144
|
-
js = 'map.addControl({controlName})'.format(controlName=control.controlName)
|
|
145
|
-
self.runJavaScriptForMap(js)
|
|
146
|
-
return self
|
|
147
|
-
|
|
148
|
-
def removeControl(self, control):
|
|
149
|
-
if control not in self._controls:
|
|
150
|
-
# TODO Should we raise a ValueError here? Or just return
|
|
151
|
-
return
|
|
152
|
-
self._controls.remove(control)
|
|
153
|
-
control.map = None
|
|
154
|
-
js = 'map.removeControl({controlName})'.format(controlName=control.controlName)
|
|
155
|
-
self.runJavaScriptForMap(js)
|
|
156
|
-
return self
|
|
157
|
-
|
|
158
|
-
def getJsresponseForMap(self, js, callback):
|
|
159
|
-
return self.getJsResponse(js, self.mapWidgetIndex, callback)
|
|
160
|
-
|
|
161
|
-
def getBounds(self, callback):
|
|
162
|
-
return self.getJsresponseForMap('map.getBounds()', callback)
|
|
163
|
-
|
|
164
|
-
def getCenter(self, callback):
|
|
165
|
-
return self.getJsresponseForMap('map.getCenter()', callback)
|
|
166
|
-
|
|
167
|
-
def getZoom(self, callback):
|
|
168
|
-
return self.getJsresponseForMap('map.getZoom()', callback)
|
|
169
|
-
|
|
170
|
-
def getState(self, callback):
|
|
171
|
-
return self.getJsresponseForMap('getMapState()', callback)
|
|
172
|
-
|
|
173
|
-
def hasLayer(self, layer):
|
|
174
|
-
return layer in self._layers
|
|
175
|
-
|
|
176
|
-
def setZoom(self, zoom, options=None):
|
|
177
|
-
js = 'map.setZoom({zoom}'.format(zoom=zoom)
|
|
178
|
-
if options:
|
|
179
|
-
js += ', {options}'.format(options=options)
|
|
180
|
-
js += ');'
|
|
181
|
-
self.runJavaScriptForMap(js)
|
|
182
|
-
return self
|
|
183
|
-
|
|
184
|
-
def setMaxBounds(self, bounds):
|
|
185
|
-
js = 'map.setMaxBounds({bounds})'.format(bounds=bounds)
|
|
186
|
-
self.runJavaScriptForMap(js)
|
|
187
|
-
return self
|
|
188
|
-
|
|
189
|
-
def fitBounds(self, bounds):
|
|
190
|
-
js = 'map.fitBounds({bounds})'.format(bounds=bounds)
|
|
191
|
-
self.runJavaScriptForMap(js)
|
|
192
|
-
return self
|
|
193
|
-
|
|
194
|
-
def setMaxZoom(self, zoom):
|
|
195
|
-
js = 'map.setMaxZoom({zoom})'.format(zoom=zoom)
|
|
196
|
-
self.runJavaScriptForMap(js)
|
|
197
|
-
return self
|
|
198
|
-
|
|
199
|
-
def setMinZoom(self, zoom):
|
|
200
|
-
js = 'map.setMinZoom({zoom})'.format(zoom=zoom)
|
|
201
|
-
self.runJavaScriptForMap(js)
|
|
202
|
-
return self
|
|
203
|
-
|
|
204
|
-
def panTo(self, latLng, options=None):
|
|
205
|
-
js = 'map.panTo({latLng}'.format(latLng=latLng)
|
|
206
|
-
if options:
|
|
207
|
-
js += ', {options}'.format(options=options)
|
|
208
|
-
js += ');'
|
|
209
|
-
self.runJavaScriptForMap(js)
|
|
210
|
-
return self
|
|
211
|
-
|
|
212
|
-
def flyTo(self, latLng, zoom=None, options=None):
|
|
213
|
-
js = 'map.flyTo({latLng}'.format(latLng=latLng)
|
|
214
|
-
if zoom:
|
|
215
|
-
js += ', {zoom}'.format(zoom=zoom)
|
|
216
|
-
if options:
|
|
217
|
-
js += ', {options}'.format(options=options)
|
|
218
|
-
js += ');'
|
|
219
|
-
self.runJavaScriptForMap(js)
|
|
220
|
-
return self
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
from qtpy.QtCore import QEventLoop, Qt, QUrl
|
|
4
|
-
from qtpy.QtWebChannel import QWebChannel
|
|
5
|
-
from qtpy.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class MapWidget(QWebEngineView):
|
|
9
|
-
"""
|
|
10
|
-
The MapWidget class is a QWebEngineView that houses the leaflet map.
|
|
11
|
-
Since it is a QWidget, it can be added to any QLayout.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
@property
|
|
15
|
-
def page(self):
|
|
16
|
-
return self._page
|
|
17
|
-
|
|
18
|
-
@property
|
|
19
|
-
def channel(self):
|
|
20
|
-
return self._channel
|
|
21
|
-
|
|
22
|
-
def __init__(self, use_file_absolute_path: bool = True, alternative_base_path: str=""):
|
|
23
|
-
super().__init__()
|
|
24
|
-
if use_file_absolute_path or len(alternative_base_path) == 0:
|
|
25
|
-
self.base_path = os.path.dirname(os.path.abspath(__file__))
|
|
26
|
-
else:
|
|
27
|
-
self.base_path = alternative_base_path
|
|
28
|
-
self._page = QWebEnginePage()
|
|
29
|
-
self.setPage(self._page)
|
|
30
|
-
self._channel = QWebChannel()
|
|
31
|
-
self._page.setWebChannel(self._channel)
|
|
32
|
-
self._loadPage()
|
|
33
|
-
self.setContextMenuPolicy(Qt.NoContextMenu)
|
|
34
|
-
|
|
35
|
-
def _get_page_path(self):
|
|
36
|
-
return os.path.join(self.base_path, 'web', 'map.html')
|
|
37
|
-
|
|
38
|
-
def _loadPage(self):
|
|
39
|
-
html_path = self._get_page_path()
|
|
40
|
-
# QEventLoop is used to make the page loading behave syncronously
|
|
41
|
-
init_loop = QEventLoop()
|
|
42
|
-
self._page.loadFinished.connect(init_loop.quit)
|
|
43
|
-
self._page.load(QUrl().fromLocalFile(html_path))
|
|
44
|
-
init_loop.exec_()
|
|
45
|
-
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
function copyWithoutCircularReferences(references, object) {
|
|
2
|
-
var cleanObject = {};
|
|
3
|
-
Object.keys(object).forEach(function(key) {
|
|
4
|
-
var value = object[key];
|
|
5
|
-
if (value && typeof value === 'object') {
|
|
6
|
-
if (references.indexOf(value) < 0) {
|
|
7
|
-
references.push(value);
|
|
8
|
-
cleanObject[key] = copyWithoutCircularReferences(references, value);
|
|
9
|
-
references.pop();
|
|
10
|
-
} else {
|
|
11
|
-
cleanObject[key] = '###_Circular_###';
|
|
12
|
-
}
|
|
13
|
-
} else if (typeof value !== 'function') {
|
|
14
|
-
cleanObject[key] = value;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return cleanObject;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// NOTE: There is an assumption here that the map var will be called map
|
|
21
|
-
// Might not be the case if there are multiple maps.
|
|
22
|
-
function getMapState() {
|
|
23
|
-
var center = map.getCenter();
|
|
24
|
-
var zoom = map.getZoom();
|
|
25
|
-
var bounds = map.getBounds();
|
|
26
|
-
var minZoom = map.getMinZoom();
|
|
27
|
-
var maxZoom = map.getMaxZoom();
|
|
28
|
-
var size = map.getSize();
|
|
29
|
-
var pixelBounds = map.getPixelBounds();
|
|
30
|
-
var pixelOrigin = map.getPixelOrigin();
|
|
31
|
-
var pixelWorldBounds = map.getPixelWorldBounds();
|
|
32
|
-
return {
|
|
33
|
-
center: center,
|
|
34
|
-
zoom: zoom,
|
|
35
|
-
bounds: bounds,
|
|
36
|
-
minZoom: minZoom,
|
|
37
|
-
maxZoom: maxZoom,
|
|
38
|
-
size: size,
|
|
39
|
-
pixelBounds: pixelBounds,
|
|
40
|
-
pixelOrigin: pixelOrigin,
|
|
41
|
-
pixelWorldBounds: pixelWorldBounds
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>Map</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<!-- Leaflet CSS -->
|
|
8
|
-
<link rel="stylesheet" href="modules/leaflet_193/leaflet.css"/>
|
|
9
|
-
<link rel="stylesheet" href="modules/leaflet_draw_414/leaflet.draw.css"/>
|
|
10
|
-
<!-- QWebChannel -->
|
|
11
|
-
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
|
12
|
-
</head>
|
|
13
|
-
<body style="margin: 0px">
|
|
14
|
-
<div id="map" style="width: 100vw; height: 100vh;"></div>
|
|
15
|
-
<!-- Leaflet JS -->
|
|
16
|
-
<script src='modules/leaflet_193/leaflet.js'></script>
|
|
17
|
-
<script src='modules/leaflet_draw_414/leaflet.draw.js'></script>
|
|
18
|
-
<script src='modules/leaflet_rotatedMarker_020/leaflet.rotatedMarker.js'></script>
|
|
19
|
-
<!-- Custom JS -->
|
|
20
|
-
<script src='custom.js'></script>
|
|
21
|
-
</body>
|
|
22
|
-
</html>
|
|
23
|
-
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|