q3dviewer 1.0.3__py3-none-any.whl → 1.0.5__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 (43) hide show
  1. q3dviewer/__init__.py +5 -0
  2. q3dviewer/base_glwidget.py +256 -0
  3. q3dviewer/base_item.py +57 -0
  4. q3dviewer/custom_items/__init__.py +9 -0
  5. q3dviewer/custom_items/axis_item.py +148 -0
  6. q3dviewer/custom_items/cloud_io_item.py +79 -0
  7. q3dviewer/custom_items/cloud_item.py +314 -0
  8. q3dviewer/custom_items/frame_item.py +194 -0
  9. q3dviewer/custom_items/gaussian_item.py +254 -0
  10. q3dviewer/custom_items/grid_item.py +88 -0
  11. q3dviewer/custom_items/image_item.py +172 -0
  12. q3dviewer/custom_items/line_item.py +120 -0
  13. q3dviewer/custom_items/text_item.py +63 -0
  14. q3dviewer/gau_io.py +0 -0
  15. q3dviewer/glwidget.py +131 -0
  16. q3dviewer/shaders/cloud_frag.glsl +28 -0
  17. q3dviewer/shaders/cloud_vert.glsl +72 -0
  18. q3dviewer/shaders/gau_frag.glsl +42 -0
  19. q3dviewer/shaders/gau_prep.glsl +249 -0
  20. q3dviewer/shaders/gau_vert.glsl +77 -0
  21. q3dviewer/shaders/sort_by_key.glsl +56 -0
  22. q3dviewer/tools/__init__.py +1 -0
  23. q3dviewer/tools/cloud_viewer.py +123 -0
  24. q3dviewer/tools/example_viewer.py +47 -0
  25. q3dviewer/tools/gaussian_viewer.py +60 -0
  26. q3dviewer/tools/lidar_calib.py +294 -0
  27. q3dviewer/tools/lidar_cam_calib.py +314 -0
  28. q3dviewer/tools/ros_viewer.py +85 -0
  29. q3dviewer/utils/__init__.py +4 -0
  30. q3dviewer/utils/cloud_io.py +323 -0
  31. q3dviewer/utils/convert_ros_msg.py +49 -0
  32. q3dviewer/utils/gl_helper.py +40 -0
  33. q3dviewer/utils/maths.py +168 -0
  34. q3dviewer/utils/range_slider.py +86 -0
  35. q3dviewer/viewer.py +58 -0
  36. q3dviewer-1.0.5.dist-info/LICENSE +21 -0
  37. {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/METADATA +7 -4
  38. q3dviewer-1.0.5.dist-info/RECORD +41 -0
  39. q3dviewer-1.0.5.dist-info/top_level.txt +1 -0
  40. q3dviewer-1.0.3.dist-info/RECORD +0 -5
  41. q3dviewer-1.0.3.dist-info/top_level.txt +0 -1
  42. {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/WHEEL +0 -0
  43. {q3dviewer-1.0.3.dist-info → q3dviewer-1.0.5.dist-info}/entry_points.txt +0 -0
q3dviewer/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ from q3dviewer.custom_items import *
2
+ from q3dviewer.glwidget import *
3
+ from q3dviewer.viewer import *
4
+ from q3dviewer.base_item import *
5
+ from q3dviewer.base_glwidget import *
@@ -0,0 +1,256 @@
1
+ """
2
+ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
+ Distributed under MIT license. See LICENSE for more information.
4
+ """
5
+
6
+ from OpenGL.GL import *
7
+ from math import radians, tan
8
+ import numpy as np
9
+ from PySide6 import QtCore, QtGui, QtOpenGLWidgets
10
+ from q3dviewer.utils.maths import frustum, euler_to_matrix, makeT
11
+
12
+
13
+ class BaseGLWidget(QtOpenGLWidgets.QOpenGLWidget):
14
+ def __init__(self, parent=None):
15
+ QtOpenGLWidgets.QOpenGLWidget.__init__(self, parent)
16
+ self.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
17
+ self.reset()
18
+ self._fov = 60
19
+ self.items = []
20
+ self.keyTimer = QtCore.QTimer()
21
+ self.color = np.array([0, 0, 0, 0])
22
+ self.dist = 40
23
+ self.euler = np.array([np.pi/3, 0, np.pi/4])
24
+ self.center = np.array([0, 0, 0.])
25
+ self.active_keys = set()
26
+ self.show_center = False
27
+ self.enable_show_center = True
28
+
29
+ def keyPressEvent(self, ev: QtGui.QKeyEvent):
30
+ if ev.key() == QtCore.Qt.Key_Up or \
31
+ ev.key() == QtCore.Qt.Key_Down or \
32
+ ev.key() == QtCore.Qt.Key_Left or \
33
+ ev.key() == QtCore.Qt.Key_Right or \
34
+ ev.key() == QtCore.Qt.Key_Z or \
35
+ ev.key() == QtCore.Qt.Key_X or \
36
+ ev.key() == QtCore.Qt.Key_A or \
37
+ ev.key() == QtCore.Qt.Key_D or \
38
+ ev.key() == QtCore.Qt.Key_W or \
39
+ ev.key() == QtCore.Qt.Key_S:
40
+ self.active_keys.add(ev.key())
41
+ self.active_keys.add(ev.key())
42
+
43
+ def keyReleaseEvent(self, ev: QtGui.QKeyEvent):
44
+ self.active_keys.discard(ev.key())
45
+
46
+ def current_width(self):
47
+ """
48
+ Return the current width of the widget.
49
+ """
50
+ return int(self.width() * self.devicePixelRatioF())
51
+
52
+ def current_height(self):
53
+ """
54
+ Return the current height of the widget.
55
+ """
56
+ return int(self.height() * self.devicePixelRatioF())
57
+
58
+ def reset(self):
59
+ pass
60
+
61
+ def add_item(self, item):
62
+ """
63
+ Add the item to the glwidget.
64
+ """
65
+ self.items.append(item)
66
+ item.set_glwidget(self)
67
+
68
+ def remove_item(self, item):
69
+ """
70
+ Remove the item from the glwidget.
71
+ """
72
+ self.items.remove(item)
73
+ item.set_glwidget(None)
74
+
75
+ def clear(self):
76
+ """
77
+ Remove all items from the glwidget.
78
+ """
79
+ for item in self.items:
80
+ item.set_glwidget(None)
81
+ self.items = []
82
+
83
+ def initializeGL(self):
84
+ """
85
+ the method is herted from QOpenGLWidget,
86
+ and it is called when the widget is first shown.
87
+ """
88
+ for item in self.items:
89
+ item.initialize()
90
+
91
+ def mouseReleaseEvent(self, ev):
92
+ if hasattr(self, 'mousePos'):
93
+ delattr(self, 'mousePos')
94
+
95
+ def update_dist(self, delta):
96
+ self.dist += delta
97
+ if self.dist < 0.1:
98
+ self.dist = 0.1
99
+
100
+ def wheelEvent(self, ev):
101
+ delta = ev.angleDelta().x()
102
+ if delta == 0:
103
+ delta = ev.angleDelta().y()
104
+ self.update_dist(-delta * self.dist * 0.001)
105
+ self.show_center = True
106
+
107
+ def mouseMoveEvent(self, ev):
108
+ lpos = ev.localPos()
109
+ if not hasattr(self, 'mousePos'):
110
+ self.mousePos = lpos
111
+ diff = lpos - self.mousePos
112
+ self.mousePos = lpos
113
+ if ev.buttons() == QtCore.Qt.MouseButton.RightButton:
114
+ rot_speed = 0.2
115
+ dyaw = radians(-diff.x() * rot_speed)
116
+ droll = radians(-diff.y() * rot_speed)
117
+ self.rotate(droll, 0, dyaw)
118
+ elif ev.buttons() == QtCore.Qt.MouseButton.LeftButton:
119
+ Rwc = euler_to_matrix(self.euler)
120
+ Kinv = np.linalg.inv(self.get_K())
121
+ dist = max(self.dist, 0.5)
122
+ self.center += Rwc @ Kinv @ np.array([-diff.x(), diff.y(), 0]) * dist
123
+ self.show_center = True
124
+
125
+ def paintGL(self):
126
+ self.update_model_projection()
127
+ self.update_model_view()
128
+ bgcolor = self.color
129
+ glClearColor(*bgcolor)
130
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)
131
+ for item in self.items:
132
+ if not item.visible():
133
+ continue
134
+ glMatrixMode(GL_MODELVIEW)
135
+ glPushMatrix()
136
+ glPushAttrib(GL_ALL_ATTRIB_BITS)
137
+ item.paint()
138
+ glPopAttrib()
139
+ glMatrixMode(GL_MODELVIEW)
140
+ glPopMatrix()
141
+
142
+ # Show center as a point if updated by mouse move event
143
+ if self.enable_show_center and self.show_center:
144
+ point_size = np.clip((self.get_K()[0, 0] / self.dist), 10, 100)
145
+ glPointSize(point_size)
146
+ glBegin(GL_POINTS)
147
+ glColor3f(1.0, 0.0, 0.0) # Red color for the center point
148
+ glVertex3f(*self.center)
149
+ glEnd()
150
+ self.show_center = False
151
+
152
+ def update_movement(self):
153
+ """
154
+ Update the movement of the camera based on the active keys.
155
+ """
156
+ if not self.active_keys:
157
+ return
158
+ rot_speed = 0.5
159
+ trans_speed = max(self.dist * 0.005, 0.1)
160
+ # Handle rotation keys
161
+ if QtCore.Qt.Key_Up in self.active_keys:
162
+ self.rotate(radians(rot_speed), 0, 0)
163
+ if QtCore.Qt.Key_Down in self.active_keys:
164
+ self.rotate(radians(-rot_speed), 0, 0)
165
+ if QtCore.Qt.Key_Left in self.active_keys:
166
+ self.rotate(0, 0, radians(rot_speed))
167
+ if QtCore.Qt.Key_Right in self.active_keys:
168
+ self.rotate(0, 0, radians(-rot_speed))
169
+ # Handle zoom keys
170
+ xz_keys = {QtCore.Qt.Key_Z, QtCore.Qt.Key_X}
171
+ if self.active_keys & xz_keys:
172
+ Rwc = euler_to_matrix(self.euler)
173
+ if QtCore.Qt.Key_Z in self.active_keys:
174
+ self.center += Rwc @ np.array([0, 0, -trans_speed])
175
+ if QtCore.Qt.Key_X in self.active_keys:
176
+ self.center += Rwc @ np.array([0, 0, trans_speed])
177
+ # Handle translation keys on the z plane
178
+ dir_keys = {QtCore.Qt.Key_W, QtCore.Qt.Key_S, QtCore.Qt.Key_A, QtCore.Qt.Key_D}
179
+ if self.active_keys & dir_keys:
180
+ Rz = euler_to_matrix([0, 0, self.euler[2]])
181
+ if QtCore.Qt.Key_W in self.active_keys:
182
+ self.center += Rz @ np.array([0, trans_speed, 0])
183
+ if QtCore.Qt.Key_S in self.active_keys:
184
+ self.center += Rz @ np.array([0, -trans_speed, 0])
185
+ if QtCore.Qt.Key_A in self.active_keys:
186
+ self.center += Rz @ np.array([-trans_speed, 0, 0])
187
+ if QtCore.Qt.Key_D in self.active_keys:
188
+ self.center += Rz @ np.array([trans_speed, 0, 0])
189
+
190
+ def update_model_view(self):
191
+ m = self.get_view_matrix()
192
+ glMatrixMode(GL_MODELVIEW)
193
+ glLoadMatrixf(m.T)
194
+
195
+ def get_view_matrix(self):
196
+ twc = self.center
197
+ tcw = np.array([0, 0, self.dist])
198
+ Rwc = euler_to_matrix(self.euler)
199
+ twc = twc + Rwc @ tcw
200
+ Twc = makeT(Rwc, twc)
201
+ return np.linalg.inv(Twc)
202
+
203
+ def set_cam_position(self, **kwargs):
204
+ pos = kwargs.get('pos', None)
205
+ distance = kwargs.get('distance', None)
206
+ if pos is not None:
207
+ self.center = pos
208
+ if distance is not None:
209
+ self.dist = distance
210
+
211
+ def set_color(self, color):
212
+ self.color = color
213
+
214
+ def update(self):
215
+ self.update_movement()
216
+ super().update()
217
+
218
+ def update_model_projection(self):
219
+ m = self.get_projection_matrix()
220
+ glMatrixMode(GL_PROJECTION)
221
+ glLoadMatrixf(m.T)
222
+
223
+ def get_projection_matrix(self):
224
+ w, h = self.current_width(), self.current_height()
225
+ dist = self.dist
226
+ near = dist * 0.001
227
+ far = dist * 10000.
228
+ r = near * tan(0.5 * radians(self._fov))
229
+ t = r * h / w
230
+ matrix = frustum(-r, r, -t, t, near, far)
231
+ return matrix
232
+
233
+ def get_K(self):
234
+ project_matrix = self.get_projection_matrix()
235
+ width = self.current_width()
236
+ height = self.current_height()
237
+ fx = project_matrix[0, 0] * width / 2
238
+ fy = project_matrix[1, 1] * height / 2
239
+ cx = width / 2
240
+ cy = height / 2
241
+ K = np.array([
242
+ [fx, 0, cx],
243
+ [0, fy, cy],
244
+ [0, 0, 1]
245
+ ])
246
+ return K
247
+
248
+ def rotate(self, rx=0, ry=0, rz=0):
249
+ # update the euler angles
250
+ self.euler += np.array([rx, ry, rz])
251
+ self.euler[2] = (self.euler[2] + np.pi) % (2 * np.pi) - np.pi
252
+ self.euler[1] = (self.euler[1] + np.pi) % (2 * np.pi) - np.pi
253
+ self.euler[0] = np.clip(self.euler[0], 0, np.pi)
254
+
255
+ def change_show_center(self, state):
256
+ self.enable_show_center = state
q3dviewer/base_item.py ADDED
@@ -0,0 +1,57 @@
1
+ """
2
+ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
+ Distributed under MIT license. See LICENSE for more information.
4
+ """
5
+
6
+ from PySide6 import QtCore
7
+ import numpy as np
8
+
9
+ class BaseItem(QtCore.QObject):
10
+ _next_id = 0
11
+
12
+ def __init__(self):
13
+ super().__init__()
14
+ self._id = BaseItem._next_id
15
+ BaseItem._next_id += 1
16
+ self._glwidget = None
17
+ self._visible = True
18
+ self._initialized = False
19
+
20
+ def set_glwidget(self, v):
21
+ self._glwidget = v
22
+
23
+ def glwidget(self):
24
+ return self._glwidget
25
+
26
+ def hide(self):
27
+ self._visible = False
28
+
29
+ def show(self):
30
+ self._visible = True
31
+
32
+ def set_visible(self, vis):
33
+ self._visible = vis
34
+
35
+ def visible(self):
36
+ return self._visible
37
+
38
+ def initialize(self):
39
+ if not self._initialized:
40
+ self.initialize_gl()
41
+
42
+ def initialize_gl(self):
43
+ """
44
+ Initialize OpenGL resources for the item.
45
+ This method should be overridden by subclasses to set up any necessary OpenGL resources.
46
+ """
47
+ pass
48
+
49
+ def paint(self):
50
+ """
51
+ Render the item using OpenGL.
52
+ This method should be overridden by subclasses to perform the actual rendering.
53
+ """
54
+ pass
55
+
56
+
57
+
@@ -0,0 +1,9 @@
1
+ from q3dviewer.custom_items.axis_item import *
2
+ from q3dviewer.custom_items.cloud_item import *
3
+ from q3dviewer.custom_items.cloud_io_item import *
4
+ from q3dviewer.custom_items.gaussian_item import *
5
+ from q3dviewer.custom_items.frame_item import *
6
+ from q3dviewer.custom_items.grid_item import *
7
+ from q3dviewer.custom_items.text_item import *
8
+ from q3dviewer.custom_items.image_item import *
9
+ from q3dviewer.custom_items.line_item import *
@@ -0,0 +1,148 @@
1
+ """
2
+ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
+ Distributed under MIT license. See LICENSE for more information.
4
+ """
5
+
6
+ from q3dviewer.base_item import BaseItem
7
+ from q3dviewer.utils import set_uniform
8
+ from OpenGL.GL import *
9
+ import numpy as np
10
+ from OpenGL.GL import shaders
11
+ from PySide6.QtWidgets import QLabel, QDoubleSpinBox
12
+
13
+
14
+ # Vertex and Fragment shader source code
15
+ vertex_shader_source = """
16
+ #version 330 core
17
+ layout(location = 0) in vec3 position;
18
+ layout(location = 1) in vec3 color;
19
+
20
+ out vec3 ourColor;
21
+
22
+ uniform mat4 view_matrix;
23
+ uniform mat4 project_matrix;
24
+ uniform mat4 model_matrix;
25
+ uniform float size;
26
+
27
+ void main()
28
+ {
29
+ vec3 scaled_position = position * size;
30
+ gl_Position = project_matrix * view_matrix * model_matrix * vec4(scaled_position, 1.0);
31
+ ourColor = color;
32
+ }
33
+ """
34
+
35
+ fragment_shader_source = """
36
+ #version 330 core
37
+ in vec3 ourColor;
38
+ out vec4 color;
39
+
40
+ void main()
41
+ {
42
+ color = vec4(ourColor, 1.0);
43
+ }
44
+ """
45
+
46
+
47
+ class AxisItem(BaseItem):
48
+ def __init__(self, size=1.0, width=2):
49
+ super().__init__()
50
+ self.size = size
51
+ self.width = width
52
+ self.model_matrix = np.eye(4, dtype=np.float32)
53
+ self.need_update_setting = True
54
+
55
+ def initialize_gl(self):
56
+ # Axis vertices and colors
57
+ self.vertices = np.array([
58
+ # positions # colors
59
+ [0.0, 0.0, 0.0, 1.0, 0.0, 0.0], # X axis (red)
60
+ [1.0, 0.0, 0.0, 1.0, 0.0, 0.0],
61
+ [0.0, 0.0, 0.0, 0.0, 1.0, 0.0], # Y axis (green)
62
+ [0.0, 1.0, 0.0, 0.0, 1.0, 0.0],
63
+ [0.0, 0.0, 0.0, 0.0, 0.0, 1.0], # Z axis (blue)
64
+ [0.0, 0.0, 1.0, 0.0, 0.0, 1.0],
65
+ ], dtype=np.float32)
66
+
67
+ self.vao = glGenVertexArrays(1)
68
+ vbo = glGenBuffers(1)
69
+
70
+ glBindVertexArray(self.vao)
71
+
72
+ glBindBuffer(GL_ARRAY_BUFFER, vbo)
73
+ glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
74
+
75
+ # Vertex positions
76
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0))
77
+ glEnableVertexAttribArray(0)
78
+
79
+ # Vertex colors
80
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
81
+ glEnableVertexAttribArray(1)
82
+
83
+ # Compile shaders and create shader program
84
+ self.program = shaders.compileProgram(
85
+ shaders.compileShader(vertex_shader_source, GL_VERTEX_SHADER),
86
+ shaders.compileShader(fragment_shader_source, GL_FRAGMENT_SHADER),
87
+ )
88
+
89
+ glBindVertexArray(0)
90
+
91
+ def add_setting(self, layout):
92
+ label_size = QLabel("Set size:")
93
+ layout.addWidget(label_size)
94
+ spinbox_size = QDoubleSpinBox()
95
+ spinbox_size.setSingleStep(0.1)
96
+ layout.addWidget(spinbox_size)
97
+ spinbox_size.setValue(self.size)
98
+ spinbox_size.valueChanged.connect(self.set_size)
99
+ spinbox_size.setRange(0.0, 100)
100
+
101
+ label_width = QLabel("Set width:")
102
+ layout.addWidget(label_width)
103
+ spinbox_width = QDoubleSpinBox()
104
+ layout.addWidget(spinbox_width)
105
+ spinbox_width.setSingleStep(0.1)
106
+ spinbox_width.setValue(self.width)
107
+ spinbox_width.valueChanged.connect(self.set_width)
108
+ spinbox_width.setRange(0, 1000)
109
+
110
+ def set_size(self, size):
111
+ self.size = size
112
+ self.need_update_setting = True
113
+
114
+ def update_setting(self):
115
+ if not self.need_update_setting:
116
+ return
117
+ glUseProgram(self.program)
118
+ set_uniform(self.program, float(self.size), 'size')
119
+ set_uniform(self.program, self.model_matrix, 'model_matrix')
120
+ glUseProgram(0)
121
+ self.need_update_setting = False
122
+
123
+ def set_width(self, width):
124
+ self.width = width
125
+
126
+ def set_transform(self, transform):
127
+ """
128
+ Set the transformation matrix for the axis item.
129
+ """
130
+ self.model_matrix = transform
131
+ self.need_update_setting = True
132
+
133
+ def paint(self):
134
+ self.update_setting()
135
+ glLineWidth(self.width)
136
+ glUseProgram(self.program)
137
+ glBindVertexArray(self.vao)
138
+
139
+ view_matrix = self.glwidget().get_view_matrix()
140
+ project_matrix = self.glwidget().get_projection_matrix()
141
+ set_uniform(self.program, view_matrix, 'view_matrix')
142
+ set_uniform(self.program, project_matrix, 'project_matrix')
143
+
144
+ glDrawArrays(GL_LINES, 0, 6)
145
+
146
+ glBindVertexArray(0)
147
+ glUseProgram(0)
148
+ glLineWidth(1)
@@ -0,0 +1,79 @@
1
+ """
2
+ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
+ Distributed under MIT license. See LICENSE for more information.
4
+ """
5
+
6
+ from q3dviewer.custom_items.cloud_item import CloudItem
7
+ from pathlib import Path
8
+ import os
9
+ from PySide6.QtWidgets import QPushButton, QLabel, QLineEdit, QMessageBox
10
+ from q3dviewer.utils.cloud_io import save_pcd, save_ply, save_e57, save_las, load_pcd, load_ply, load_e57, load_las
11
+
12
+ class CloudIOItem(CloudItem):
13
+ """
14
+ add save/load function to CloudItem
15
+ """
16
+ def __init__(self, **kwargs):
17
+ super().__init__(**kwargs)
18
+ self.save_path = str(Path(os.path.expanduser("~"), "data.pcd"))
19
+
20
+ def add_setting(self, layout):
21
+ super().add_setting(layout)
22
+
23
+ label4 = QLabel("Save Path:")
24
+ layout.addWidget(label4)
25
+ box4 = QLineEdit()
26
+ box4.setText(self.save_path)
27
+ box4.textChanged.connect(self.set_path)
28
+ layout.addWidget(box4)
29
+ save_button = QPushButton("Save Cloud")
30
+ save_button.clicked.connect(self.save)
31
+ layout.addWidget(save_button)
32
+ self.save_msg = QMessageBox()
33
+ self.save_msg.setIcon(QMessageBox.Information)
34
+ self.save_msg.setWindowTitle("save")
35
+ self.save_msg.setStandardButtons(QMessageBox.Ok)
36
+
37
+ def save(self):
38
+ cloud = self.buff[:self.valid_buff_top]
39
+ func = None
40
+ if self.save_path.endswith(".pcd"):
41
+ func = save_pcd
42
+ elif self.save_path.endswith(".ply"):
43
+ func = save_ply
44
+ elif self.save_path.endswith(".e57"):
45
+ func = save_e57
46
+ elif self.save_path.endswith(".las"):
47
+ func = save_las
48
+ elif self.save_path.endswith(".tif") or self.save_path.endswith(".tiff"):
49
+ print("Do not support save as tif type!")
50
+ else:
51
+ print("Unsupported cloud file type!")
52
+ try:
53
+ func(cloud, self.save_path)
54
+ self.save_msg.setText("Save cloud to %s" % self.save_path)
55
+ except Exception as e:
56
+ print(e)
57
+ self.save_msg.setText("Cannot save to %s" % self.save_path)
58
+ self.save_msg.exec()
59
+ self.save_msg.exec()
60
+
61
+ def load(self, file, append=False):
62
+ # print("Try to load %s ..." % file)
63
+ if file.endswith(".pcd"):
64
+ cloud, color_mode = load_pcd(file)
65
+ elif file.endswith(".ply"):
66
+ cloud, color_mode = load_ply(file)
67
+ elif file.endswith(".e57"):
68
+ cloud, color_mode = load_e57(file)
69
+ elif file.endswith(".las"):
70
+ cloud, color_mode = load_las(file)
71
+ else:
72
+ print("Not supported file type.")
73
+ return
74
+ self.set_data(data=cloud, append=append)
75
+ self.set_color_mode(color_mode)
76
+ return cloud
77
+
78
+ def set_path(self, path):
79
+ self.save_path = path