q3dviewer 1.1.5__py3-none-any.whl → 1.1.6__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.
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
5
+ Distributed under MIT license. See LICENSE for more information.
6
+ """
7
+
8
+ """
9
+ You can use the following code to set the Q3D_QT_IMPL environment variable
10
+ # tested for PyQt5, PySide2 and PySide6
11
+ # -------------------------------
12
+ in your python script before importing QT:
13
+ import os
14
+ os.environ['Q3D_QT_IMPL'] = 'PySide6'
15
+ or in your bash:
16
+ export Q3D_QT_IMPL=PyQt5
17
+ # -------------------------------
18
+ """
19
+
20
+ import importlib.util
21
+ import builtins
22
+ import sys
23
+ import os
24
+
25
+
26
+ Q3D_QT_IMPL = os.environ.get('Q3D_QT_IMPL')
27
+ Q3D_DEBUG = os.environ.get('Q3D_DEBUG')
28
+
29
+ if Q3D_QT_IMPL not in ['PyQt5', 'PySide2', 'PySide6']:
30
+ Q3D_QT_IMPL = None
31
+
32
+ if Q3D_QT_IMPL is None:
33
+ if importlib.util.find_spec('PyQt5') is not None:
34
+ Q3D_QT_IMPL = 'PyQt5'
35
+ elif importlib.util.find_spec('PySide6') is not None:
36
+ Q3D_QT_IMPL = 'PySide6'
37
+ else:
38
+ raise ImportError('No Qt binding found. Please install PySide6.')
39
+
40
+
41
+ def import_module(name):
42
+ module = builtins.__import__(f'{Q3D_QT_IMPL}.{name}').__dict__[name]
43
+ sys.modules[f'{__name__}.{name}'] = module
44
+
45
+
46
+ def load_qt():
47
+ if Q3D_DEBUG is not None:
48
+ print(f'Using {Q3D_QT_IMPL} as Qt binding.')
49
+
50
+ # register common Qt modules
51
+ modules = ['QtCore', 'QtGui', 'QtWidgets']
52
+ for name in modules:
53
+ import_module(name)
54
+ # register OpenGL modules for PySide6
55
+ if Q3D_QT_IMPL == 'PySide6':
56
+ import_module('QtOpenGLWidgets')
57
+ sys.modules[f'{__name__}.QtWidgets'].QOpenGLWidget = sys.modules[f'{__name__}.QtOpenGLWidgets'].QOpenGLWidget
58
+ # make PyQt5 and PySide6 modules compatible
59
+ if Q3D_QT_IMPL == 'PyQt5':
60
+ sys.modules[f'{__name__}.QtCore'].Signal = sys.modules[f'{__name__}.QtCore'].pyqtSignal
61
+ sys.modules[f'{__name__}.QtCore'].Slot = sys.modules[f'{__name__}.QtCore'].pyqtSlot
62
+ sys.modules[f'{__name__}.QtCore'].Property = sys.modules[f'{__name__}.QtCore'].pyqtProperty
63
+ # Handle exec() for PySide2
64
+ if Q3D_QT_IMPL == 'PySide2':
65
+ sys.modules[f'{__name__}.QtWidgets'].QApplication.exec = sys.modules[f'{__name__}.QtWidgets'].QApplication.exec_
66
+
67
+
68
+ load_qt()
q3dviewer/__init__.py CHANGED
@@ -1,5 +1,14 @@
1
+ import time
2
+ t1 = time.time()
1
3
  from q3dviewer.custom_items import *
4
+ t2 = time.time()
2
5
  from q3dviewer.glwidget import *
3
6
  from q3dviewer.viewer import *
4
7
  from q3dviewer.base_item import *
5
8
  from q3dviewer.base_glwidget import *
9
+ t3 = time.time()
10
+
11
+ from q3dviewer.Qt import Q3D_DEBUG
12
+ if Q3D_DEBUG:
13
+ print("Import custom items: ", t2 - t1)
14
+ print("Import base q3dviewer: ", t3 - t2)
@@ -6,13 +6,14 @@ Distributed under MIT license. See LICENSE for more information.
6
6
  from OpenGL.GL import *
7
7
  from math import radians, tan
8
8
  import numpy as np
9
- from PySide6 import QtCore, QtGui, QtOpenGLWidgets
9
+ from q3dviewer.Qt import QtCore, QtGui
10
10
  from q3dviewer.utils.maths import frustum, euler_to_matrix, makeT
11
+ from q3dviewer.Qt.QtWidgets import QOpenGLWidget
11
12
 
12
13
 
13
- class BaseGLWidget(QtOpenGLWidgets.QOpenGLWidget):
14
+ class BaseGLWidget(QOpenGLWidget):
14
15
  def __init__(self, parent=None):
15
- QtOpenGLWidgets.QOpenGLWidget.__init__(self, parent)
16
+ QOpenGLWidget.__init__(self, parent)
16
17
  self.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
17
18
  self.reset()
18
19
  self._fov = 60
q3dviewer/base_item.py CHANGED
@@ -2,11 +2,10 @@
2
2
  Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
3
  Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
+ from q3dviewer.Qt.QtCore import QObject
5
6
 
6
- from PySide6 import QtCore
7
- import numpy as np
8
7
 
9
- class BaseItem(QtCore.QObject):
8
+ class BaseItem(QObject):
10
9
  _next_id = 0
11
10
 
12
11
  def __init__(self):
@@ -1,9 +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 *
1
+ from q3dviewer.custom_items.axis_item import AxisItem
2
+ from q3dviewer.custom_items.cloud_item import CloudItem
3
+ from q3dviewer.custom_items.cloud_io_item import CloudIOItem
4
+ from q3dviewer.custom_items.gaussian_item import GaussianItem
5
+ from q3dviewer.custom_items.frame_item import FrameItem
6
+ from q3dviewer.custom_items.grid_item import GridItem
7
+ from q3dviewer.custom_items.text_item import Text2DItem
8
+ from q3dviewer.custom_items.image_item import ImageItem
9
+ from q3dviewer.custom_items.line_item import LineItem
@@ -2,11 +2,10 @@
2
2
  Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
3
  Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
-
6
5
  from q3dviewer.base_item import BaseItem
7
6
  from OpenGL.GL import *
8
7
  import numpy as np
9
- from PySide6.QtWidgets import QDoubleSpinBox
8
+ from q3dviewer.Qt.QtWidgets import QDoubleSpinBox
10
9
 
11
10
 
12
11
  class AxisItem(BaseItem):
@@ -6,7 +6,7 @@ Distributed under MIT license. See LICENSE for more information.
6
6
  from q3dviewer.custom_items.cloud_item import CloudItem
7
7
  from pathlib import Path
8
8
  import os
9
- from PySide6.QtWidgets import QPushButton, QLabel, QLineEdit, QMessageBox
9
+ from q3dviewer.Qt.QtWidgets import QPushButton, QLabel, QLineEdit, QMessageBox
10
10
  from q3dviewer.utils.cloud_io import save_pcd, save_ply, save_e57, save_las, load_pcd, load_ply, load_e57, load_las
11
11
 
12
12
  class CloudIOItem(CloudItem):
@@ -38,12 +38,16 @@ class CloudIOItem(CloudItem):
38
38
  cloud = self.buff[:self.valid_buff_top]
39
39
  func = None
40
40
  if self.save_path.endswith(".pcd"):
41
+ from q3dviewer.utils.cloud_io import save_pcd
41
42
  func = save_pcd
42
43
  elif self.save_path.endswith(".ply"):
44
+ from q3dviewer.utils.cloud_io import save_ply
43
45
  func = save_ply
44
46
  elif self.save_path.endswith(".e57"):
47
+ from q3dviewer.utils.cloud_io import save_e57
45
48
  func = save_e57
46
49
  elif self.save_path.endswith(".las"):
50
+ from q3dviewer.utils.cloud_io import save_las
47
51
  func = save_las
48
52
  elif self.save_path.endswith(".tif") or self.save_path.endswith(".tiff"):
49
53
  print("Do not support save as tif type!")
@@ -61,12 +65,16 @@ class CloudIOItem(CloudItem):
61
65
  def load(self, file, append=False):
62
66
  # print("Try to load %s ..." % file)
63
67
  if file.endswith(".pcd"):
68
+ from q3dviewer.utils.cloud_io import load_pcd
64
69
  cloud = load_pcd(file)
65
70
  elif file.endswith(".ply"):
71
+ from q3dviewer.utils.cloud_io import load_ply
66
72
  cloud = load_ply(file)
67
73
  elif file.endswith(".e57"):
74
+ from q3dviewer.utils.cloud_io import load_e57
68
75
  cloud = load_e57(file)
69
76
  elif file.endswith(".las"):
77
+ from q3dviewer.utils.cloud_io import load_las
70
78
  cloud = load_las(file)
71
79
  else:
72
80
  print("Not supported file type.")
@@ -7,13 +7,15 @@ Distributed under MIT license. See LICENSE for more information.
7
7
  import numpy as np
8
8
  from q3dviewer.base_item import BaseItem
9
9
  from OpenGL.GL import *
10
+ from OpenGL.GL import shaders
11
+
10
12
  import threading
11
13
  import os
12
- from PySide6.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, \
13
- QComboBox, QCheckBox
14
- from OpenGL.GL import shaders
15
- from q3dviewer.utils import *
14
+ from q3dviewer.Qt.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, QComboBox, QCheckBox
16
15
  from q3dviewer.utils.range_slider import RangeSlider
16
+ from q3dviewer.utils import set_uniform
17
+ from q3dviewer.utils import text_to_rgba
18
+ from q3dviewer.Qt import Q3D_DEBUG
17
19
 
18
20
 
19
21
  # draw points with color (x, y, z, color)
@@ -143,14 +145,15 @@ class CloudItem(BaseItem):
143
145
  self.box_size.setPrefix("Set size (pixel): ")
144
146
  self.box_size.setDecimals(0)
145
147
  self.box_size.setSingleStep(1)
146
- self.box_size.setValue(1)
147
- self.size = 1
148
+ self.size = np.ceil(self.size)
149
+ self.box_size.setValue(self.size)
148
150
  else:
149
151
  self.box_size.setPrefix("Set size (meter): ")
150
152
  self.box_size.setDecimals(2)
151
153
  self.box_size.setSingleStep(0.01)
152
- self.box_size.setValue(0.01)
153
- self.size = 0.01
154
+ if self.size >= 1:
155
+ self.size = self.size * 0.01
156
+ self.box_size.setValue(self.size)
154
157
  self.need_update_setting = True
155
158
 
156
159
  def set_alpha(self, alpha):
@@ -237,7 +240,8 @@ class CloudItem(BaseItem):
237
240
  buff_capacity = self.buff.shape[0]
238
241
  while (new_buff_top > buff_capacity):
239
242
  buff_capacity += self.CAPACITY
240
- print("[Cloud Item] Update capacity to %d" % buff_capacity)
243
+ if Q3D_DEBUG is not None:
244
+ print("[Cloud Item] Update capacity to %d" % buff_capacity)
241
245
  new_buff = np.empty((buff_capacity), self.data_type)
242
246
  new_buff[:self.add_buff_loc] = self.buff[:self.add_buff_loc]
243
247
  new_buff[self.add_buff_loc:new_buff_top] = self.wait_add_data
@@ -4,11 +4,11 @@ Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
5
 
6
6
  from q3dviewer.base_item import BaseItem
7
- from OpenGL.GL import *
8
7
  import numpy as np
8
+ from OpenGL.GL import *
9
9
  from OpenGL.GL import shaders
10
- from q3dviewer.utils import *
11
-
10
+ from q3dviewer.utils import set_uniform
11
+ from q3dviewer.utils import text_to_rgba
12
12
 
13
13
  # Vertex and Fragment shader source code
14
14
  vertex_shader_source = """
@@ -8,9 +8,9 @@ from q3dviewer.base_item import BaseItem
8
8
  from OpenGL.GL import *
9
9
  import numpy as np
10
10
  import os
11
- from PySide6.QtWidgets import QComboBox, QLabel
11
+ from q3dviewer.Qt.QtWidgets import QComboBox, QLabel
12
12
  from OpenGL.GL import shaders
13
- from q3dviewer.utils import *
13
+ from q3dviewer.utils import set_uniform
14
14
 
15
15
 
16
16
  def div_round_up(x, y):
@@ -5,9 +5,9 @@ Distributed under MIT license. See LICENSE for more information.
5
5
 
6
6
  from q3dviewer.base_item import BaseItem
7
7
  from OpenGL.GL import *
8
- from PySide6.QtWidgets import QLabel, QDoubleSpinBox, QLineEdit
8
+ from q3dviewer.Qt.QtWidgets import QDoubleSpinBox
9
9
  import numpy as np
10
- from q3dviewer.utils.maths import text_to_rgba
10
+ from q3dviewer.utils import text_to_rgba
11
11
 
12
12
 
13
13
  class GridItem(BaseItem):
@@ -5,9 +5,10 @@ Distributed under MIT license. See LICENSE for more information.
5
5
 
6
6
  from q3dviewer.base_item import BaseItem
7
7
  from OpenGL.GL import *
8
+
8
9
  import numpy as np
9
10
  from OpenGL.GL import shaders
10
- from PySide6.QtWidgets import QLabel, QSpinBox, QCheckBox
11
+ from q3dviewer.Qt.QtWidgets import QSpinBox, QCheckBox
11
12
 
12
13
 
13
14
  # Vertex and Fragment shader source code
@@ -7,8 +7,8 @@ from q3dviewer.base_item import BaseItem
7
7
  from OpenGL.GL import *
8
8
  import numpy as np
9
9
  import threading
10
- from PySide6.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox
11
- from q3dviewer.utils.maths import text_to_rgba
10
+ from q3dviewer.Qt.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox
11
+ from q3dviewer.utils import text_to_rgba
12
12
 
13
13
 
14
14
  class LineItem(BaseItem):
@@ -3,10 +3,9 @@ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
3
  Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
5
 
6
- from PySide6 import QtCore, QtGui
6
+ from q3dviewer.Qt import QtCore, QtGui
7
7
  from q3dviewer.base_item import BaseItem
8
- from OpenGL.GL import *
9
- from q3dviewer.utils.maths import text_to_rgba
8
+ from q3dviewer.utils import text_to_rgba
10
9
 
11
10
 
12
11
  class Text2DItem(BaseItem):
@@ -16,12 +15,12 @@ class Text2DItem(BaseItem):
16
15
  """All keyword arguments are passed to set_data()"""
17
16
  BaseItem.__init__(self)
18
17
  self.pos = (20, 50)
19
- try:
20
- self.rgb = text_to_rgba(self.color)
21
- except ValueError:
22
- raise ValueError("Invalid color format. Use mathplotlib color format.")
23
18
  self.text = ''
24
19
  self.font = QtGui.QFont('Helvetica', 16)
20
+
21
+ self.rgb = text_to_rgba('w')
22
+ if 'pos' in kwds:
23
+ self.pos = kwds['pos']
25
24
  self.set_data(**kwds)
26
25
 
27
26
  def set_data(self, **kwds):
@@ -47,7 +46,6 @@ class Text2DItem(BaseItem):
47
46
  def set_color(self, color):
48
47
  try:
49
48
  self.rgb = text_to_rgba(color)
50
- self.color = color
51
49
  except ValueError:
52
50
  print("Invalid color format. Use mathplotlib color format.")
53
51
 
q3dviewer/glwidget.py CHANGED
@@ -3,13 +3,11 @@ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
3
  Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
5
 
6
- from PySide6 import QtCore
7
- from PySide6.QtWidgets import QWidget, QComboBox, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QCheckBox, QGroupBox
8
- from PySide6.QtGui import QKeyEvent, QVector3D
9
- from OpenGL.GL import *
10
- import numpy as np
6
+ from q3dviewer.Qt import QtCore
7
+ from q3dviewer.Qt.QtWidgets import QWidget, QComboBox, QVBoxLayout, QLabel, QLineEdit, QCheckBox, QGroupBox
8
+ from q3dviewer.Qt.QtGui import QKeyEvent
11
9
  from q3dviewer.base_glwidget import BaseGLWidget
12
- from q3dviewer.utils.maths import text_to_rgba
10
+ from q3dviewer.utils import text_to_rgba
13
11
 
14
12
  class SettingWindow(QWidget):
15
13
  def __init__(self):
@@ -7,8 +7,8 @@ Distributed under MIT license. See LICENSE for more information.
7
7
 
8
8
  import numpy as np
9
9
  import q3dviewer as q3d
10
- from PySide6.QtWidgets import QVBoxLayout, QProgressBar, QDialog, QLabel
11
- from PySide6.QtCore import QThread, Signal
10
+ from q3dviewer.Qt.QtWidgets import QVBoxLayout, QProgressBar, QDialog, QLabel
11
+ from q3dviewer.Qt.QtCore import QThread, Signal
12
12
 
13
13
 
14
14
  class ProgressDialog(QDialog):
@@ -2,7 +2,7 @@
2
2
 
3
3
  import numpy as np
4
4
  import q3dviewer as q3d
5
- from PySide6.QtCore import QTimer
5
+ from q3dviewer.Qt.QtCore import QTimer
6
6
 
7
7
  i = 0.0
8
8
 
@@ -7,22 +7,23 @@ Distributed under MIT license. See LICENSE for more information.
7
7
 
8
8
  import numpy as np
9
9
  import q3dviewer as q3d
10
- from PySide6.QtWidgets import QVBoxLayout, QListWidget, QListWidgetItem, QPushButton, QDoubleSpinBox, QCheckBox, QLineEdit, QMessageBox, QLabel, QHBoxLayout, QDockWidget, QWidget, QComboBox
11
- from PySide6.QtCore import QTimer
12
- from q3dviewer.tools.cloud_viewer import ProgressDialog, FileLoaderThread
13
- from PySide6 import QtCore
14
- from PySide6.QtGui import QKeyEvent
10
+ from q3dviewer.Qt.QtWidgets import QVBoxLayout, QListWidget, QListWidgetItem, QPushButton, QDoubleSpinBox, QCheckBox, QLineEdit, QMessageBox, QLabel, QHBoxLayout, QDockWidget, QWidget, QComboBox
11
+ from q3dviewer.Qt.QtCore import QTimer
12
+ from q3dviewer.Qt.QtGui import QKeyEvent
13
+ from q3dviewer.Qt import QtCore
15
14
  from q3dviewer import GLWidget
15
+ from q3dviewer.tools.cloud_viewer import ProgressDialog, FileLoaderThread
16
+
16
17
  import imageio.v2 as imageio
17
18
  import os
18
-
19
+ from q3dviewer.utils.maths import matrix_to_euler, interpolate_pose
19
20
 
20
21
  def recover_center_euler(Twc, dist):
21
22
  Rwc = Twc[:3, :3] # Extract rotation
22
23
  twc = Twc[:3, 3] # Extract translation
23
24
  tco = np.array([0, 0, dist]) # Camera frame origin
24
25
  two = twc - Rwc @ tco # Compute center
25
- euler = q3d.matrix_to_euler(Rwc)
26
+ euler = matrix_to_euler(Rwc)
26
27
  return two, euler
27
28
 
28
29
 
@@ -247,7 +248,7 @@ class CMMViewer(q3d.Viewer):
247
248
  for j in range(num_steps):
248
249
  self.frames.append([i, current_frame.Twc])
249
250
  next_frame = self.key_frames[i + 1]
250
- Ts = q3d.interpolate_pose(current_frame.Twc, next_frame.Twc,
251
+ Ts = interpolate_pose(current_frame.Twc, next_frame.Twc,
251
252
  current_frame.lin_vel,
252
253
  current_frame.ang_vel,
253
254
  dt)
@@ -10,10 +10,11 @@ import rospy
10
10
  import numpy as np
11
11
  import argparse
12
12
  import q3dviewer as q3d
13
- from PySide6.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, \
14
- QSpinBox, QWidget, QVBoxLayout, QHBoxLayout, QPushButton
15
- from PySide6 import QtCore
13
+ from q3dviewer.Qt.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, QSpinBox, QWidget, QVBoxLayout, QHBoxLayout, QPushButton
14
+ from q3dviewer.Qt import QtCore
16
15
  from q3dviewer.utils.convert_ros_msg import convert_pointcloud2_msg
16
+ from q3dviewer.utils.maths import matrix_to_quaternion, euler_to_matrix, matrix_to_euler
17
+
17
18
 
18
19
  try:
19
20
  import open3d as o3d
@@ -123,7 +124,7 @@ class LiDARCalibViewer(q3d.Viewer):
123
124
 
124
125
  self.line_trans.setText(
125
126
  f"[{self.t01[0]:.6f}, {self.t01[1]:.6f}, {self.t01[2]:.6f}]")
126
- quat = q3d.matrix_to_quaternion(self.R01)
127
+ quat = matrix_to_quaternion(self.R01)
127
128
  self.line_quat.setText(
128
129
  f"[{quat[0]:.6f}, {quat[1]:.6f}, {quat[2]:.6f}, {quat[3]:.6f}]")
129
130
 
@@ -155,8 +156,8 @@ class LiDARCalibViewer(q3d.Viewer):
155
156
  roll = self.box_roll.value()
156
157
  pitch = self.box_pitch.value()
157
158
  yaw = self.box_yaw.value()
158
- self.R01 = q3d.euler_to_matrix(np.array([roll, pitch, yaw]))
159
- quat = q3d.matrix_to_quaternion(self.R01)
159
+ self.R01 = euler_to_matrix(np.array([roll, pitch, yaw]))
160
+ quat = matrix_to_quaternion(self.R01)
160
161
  self.line_quat.setText(
161
162
  f"[{quat[0]:.6f}, {quat[1]:.6f}, {quat[2]:.6f}, {quat[3]:.6f}]")
162
163
 
@@ -202,8 +203,8 @@ class LiDARCalibViewer(q3d.Viewer):
202
203
  t01 = transformation_icp[:3, 3]
203
204
 
204
205
  # Update the UI with new values
205
- quat = q3d.matrix_to_quaternion(R01)
206
- rpy = q3d.matrix_to_euler(R01)
206
+ quat = matrix_to_quaternion(R01)
207
+ rpy = matrix_to_euler(R01)
207
208
  self.box_roll.setValue(rpy[0])
208
209
  self.box_pitch.setValue(rpy[1])
209
210
  self.box_yaw.setValue(rpy[2])
@@ -9,13 +9,15 @@ from sensor_msgs.msg import PointCloud2, Image, CameraInfo
9
9
  import rospy
10
10
  import numpy as np
11
11
  import q3dviewer as q3d
12
- from PySide6.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, \
12
+ from q3dviewer.Qt.QtWidgets import QLabel, QLineEdit, QDoubleSpinBox, \
13
13
  QSpinBox, QWidget, QVBoxLayout, QHBoxLayout, QCheckBox
14
- from PySide6 import QtCore
14
+ from q3dviewer.Qt import QtCore
15
15
  import rospy
16
16
  import cv2
17
17
  import argparse
18
18
  from q3dviewer.utils.convert_ros_msg import convert_pointcloud2_msg, convert_image_msg
19
+ from q3dviewer.utils.maths import euler_to_matrix, matrix_to_quaternion, matrix_to_euler
20
+
19
21
 
20
22
  clouds = []
21
23
  remap_info = None
@@ -42,7 +44,7 @@ class LidarCamViewer(q3d.Viewer):
42
44
  # c: camera image frame
43
45
  # l: lidar frame
44
46
  self.Rbl = np.eye(3)
45
- self.Rbl = q3d.euler_to_matrix(np.array([0.0, 0.0, 0.0]))
47
+ self.Rbl = euler_to_matrix(np.array([0.0, 0.0, 0.0]))
46
48
  self.Rcb = np.array([[0, -1, 0],
47
49
  [0, 0, -1],
48
50
  [1, 0, 0]])
@@ -104,7 +106,7 @@ class LidarCamViewer(q3d.Viewer):
104
106
  self.box_roll.setRange(-np.pi, np.pi)
105
107
  self.box_pitch.setRange(-np.pi, np.pi)
106
108
  self.box_yaw.setRange(-np.pi, np.pi)
107
- rpy = q3d.matrix_to_euler(self.Rbl)
109
+ rpy = matrix_to_euler(self.Rbl)
108
110
  self.box_roll.setValue(rpy[0])
109
111
  self.box_pitch.setValue(rpy[1])
110
112
  self.box_yaw.setValue(rpy[2])
@@ -136,7 +138,7 @@ class LidarCamViewer(q3d.Viewer):
136
138
 
137
139
  self.line_trans.setText(
138
140
  f"[{self.tcl[0]:.6f}, {self.tcl[1]:.6f}, {self.tcl[2]:.6f}]")
139
- quat = q3d.matrix_to_quaternion(self.Rcl)
141
+ quat = matrix_to_quaternion(self.Rcl)
140
142
  self.line_quat.setText(
141
143
  f"[{quat[0]:.6f}, {quat[1]:.6f}, {quat[2]:.6f}, {quat[3]:.6f}]")
142
144
 
@@ -170,9 +172,9 @@ class LidarCamViewer(q3d.Viewer):
170
172
  roll = self.box_roll.value()
171
173
  pitch = self.box_pitch.value()
172
174
  yaw = self.box_yaw.value()
173
- self.Rbl = q3d.euler_to_matrix(np.array([roll, pitch, yaw]))
175
+ self.Rbl = euler_to_matrix(np.array([roll, pitch, yaw]))
174
176
  self.Rcl = self.Rcb @ self.Rbl
175
- quat = q3d.matrix_to_quaternion(self.Rcl)
177
+ quat = matrix_to_quaternion(self.Rcl)
176
178
  self.line_quat.setText(
177
179
  f"[{quat[0]:.6f}, {quat[1]:.6f}, {quat[2]:.6f}, {quat[3]:.6f}]")
178
180
 
@@ -1,4 +1,2 @@
1
- from q3dviewer.utils.maths import *
2
- from q3dviewer.utils.gl_helper import *
3
- from q3dviewer.utils.range_slider import *
4
- from q3dviewer.utils.cloud_io import *
1
+ from q3dviewer.utils.helpers import rainbow, text_to_rgba
2
+ from q3dviewer.utils.gl_helper import set_uniform
@@ -4,13 +4,10 @@ Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
5
 
6
6
  import numpy as np
7
- import meshio
8
- from pypcd4 import PointCloud, MetaData
9
- from pye57 import E57
10
- import laspy
11
7
 
12
8
 
13
9
  def save_ply(cloud, save_path):
10
+ import meshio
14
11
  xyz = cloud['xyz']
15
12
  i = (cloud['irgb'] & 0xFF000000) >> 24
16
13
  rgb = cloud['irgb'] & 0x00FFFFFF
@@ -20,6 +17,7 @@ def save_ply(cloud, save_path):
20
17
 
21
18
 
22
19
  def load_ply(file):
20
+ import meshio
23
21
  mesh = meshio.read(file)
24
22
  xyz = mesh.points
25
23
  rgb = np.zeros([xyz.shape[0]], dtype=np.uint32)
@@ -35,6 +33,7 @@ def load_ply(file):
35
33
 
36
34
 
37
35
  def save_pcd(cloud, save_path):
36
+ from pypcd4 import PointCloud, MetaData
38
37
  fields = ('x', 'y', 'z', 'intensity', 'rgb')
39
38
  metadata = MetaData.model_validate(
40
39
  {
@@ -82,12 +81,17 @@ def save_pcd(cloud, save_path):
82
81
 
83
82
 
84
83
  def load_pcd(file):
84
+ from pypcd4 import PointCloud
85
85
  dtype = [('xyz', '<f4', (3,)), ('irgb', '<u4')]
86
86
  pc = PointCloud.from_path(file).pc_data
87
87
  rgb = np.zeros([pc.shape[0]], dtype=np.uint32)
88
88
  intensity = np.zeros([pc.shape[0]], dtype=np.uint32)
89
89
  if 'intensity' in pc.dtype.names:
90
90
  intensity = pc['intensity'].astype(np.uint32)
91
+ max_initensity = np.max(intensity)
92
+ # normalize the intensity to 0-255
93
+ if max_initensity > 255:
94
+ intensity = (intensity / max_initensity * 255).astype(np.uint32)
91
95
  if 'rgb' in pc.dtype.names:
92
96
  rgb = pc['rgb'].astype(np.uint32)
93
97
  irgb = (intensity << 24) | rgb
@@ -97,6 +101,7 @@ def load_pcd(file):
97
101
 
98
102
 
99
103
  def save_e57(cloud, save_path):
104
+ from pye57 import E57
100
105
  e57 = E57(save_path, mode='w')
101
106
  x = cloud['xyz'][:, 0]
102
107
  y = cloud['xyz'][:, 1]
@@ -113,6 +118,7 @@ def save_e57(cloud, save_path):
113
118
 
114
119
 
115
120
  def load_e57(file_path):
121
+ from pye57 import E57
116
122
  e57 = E57(file_path, mode="r")
117
123
  scans = e57.read_scan(0, ignore_missing_fields=True,
118
124
  intensity=True, colors=True)
@@ -138,6 +144,7 @@ def load_e57(file_path):
138
144
 
139
145
 
140
146
  def load_las(file):
147
+ import laspy
141
148
  with laspy.open(file) as f:
142
149
  las = f.read()
143
150
  xyz = np.vstack((las.x, las.y, las.z)).transpose()
@@ -147,21 +154,24 @@ def load_las(file):
147
154
  if 'intensity' in dimensions:
148
155
  intensity = las.intensity.astype(np.uint32)
149
156
  if 'red' in dimensions and 'green' in dimensions and 'blue' in dimensions:
150
- red = las.red
151
- green = las.green
152
- blue = las.blue
153
- max_val = np.max([red, green, blue])
154
- if red.dtype == np.dtype('uint16') and max_val > 255:
157
+ red = las.red.astype(np.uint32)
158
+ green = las.green.astype(np.uint32)
159
+ blue = las.blue.astype(np.uint32)
160
+ if np.max([red, green, blue]) > 255:
155
161
  red = (red / 255).astype(np.uint32)
156
162
  green = (green / 255).astype(np.uint32)
157
163
  blue = (blue / 255).astype(np.uint32)
158
164
  rgb = (red << 16) | (green << 8) | blue
159
- color = ((intensity / 255)<< 24) | rgb
165
+ if np.max(intensity) > 255:
166
+ intensity = (intensity / 255).astype(np.uint32)
167
+ intensity = np.clip(intensity, 0, 255)
168
+ color = (intensity << 24) | rgb
160
169
  dtype = [('xyz', '<f4', (3,)), ('irgb', '<u4')]
161
170
  cloud = np.rec.fromarrays([xyz, color], dtype=dtype)
162
171
  return cloud
163
172
 
164
173
  def save_las(cloud, save_path):
174
+ import laspy
165
175
  header = laspy.LasHeader(point_format=3, version="1.2")
166
176
  las = laspy.LasData(header)
167
177
  las.x = cloud['xyz'][:, 0]
@@ -229,6 +239,7 @@ def matrix_to_quaternion_wxyz(matrices):
229
239
 
230
240
 
231
241
  def load_gs_ply(path, T=None):
242
+ import meshio
232
243
  mesh = meshio.read(path)
233
244
  vertices = mesh.points
234
245
  pws = vertices[:, :3]
@@ -0,0 +1,97 @@
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
+ import numpy as np
7
+ from OpenGL.GL import *
8
+
9
+
10
+ def rainbow(scalars, scalar_min=0, scalar_max=255):
11
+ range = scalar_max - scalar_min
12
+ values = 1.0 - (scalars - scalar_min) / range
13
+ # values = (scalars - scalar_min) / range # using inverted color
14
+ colors = np.zeros([scalars.shape[0], 3], dtype=np.float32)
15
+ values = np.clip(values, 0, 1)
16
+
17
+ h = values * 5.0 + 1.0
18
+ i = np.floor(h).astype(int)
19
+ f = h - i
20
+ f[np.logical_not(i % 2)] = 1 - f[np.logical_not(i % 2)]
21
+ n = 1 - f
22
+
23
+ # idx = i <= 1
24
+ colors[i <= 1, 0] = n[i <= 1] * 255
25
+ colors[i <= 1, 1] = 0
26
+ colors[i <= 1, 2] = 255
27
+
28
+ colors[i == 2, 0] = 0
29
+ colors[i == 2, 1] = n[i == 2] * 255
30
+ colors[i == 2, 2] = 255
31
+
32
+ colors[i == 3, 0] = 0
33
+ colors[i == 3, 1] = 255
34
+ colors[i == 3, 2] = n[i == 3] * 255
35
+
36
+ colors[i == 4, 0] = n[i == 4] * 255
37
+ colors[i == 4, 1] = 255
38
+ colors[i == 4, 2] = 0
39
+
40
+ colors[i >= 5, 0] = 255
41
+ colors[i >= 5, 1] = n[i >= 5] * 255
42
+ colors[i >= 5, 2] = 0
43
+ return colors
44
+
45
+
46
+ def text_to_rgba(color_text, flat=False):
47
+ """
48
+ Convert a color text to an RGBA tuple.
49
+
50
+ :param color_text: e.g. '#FF0000', '#FF0000FF', 'red', 'green', 'blue', 'yellow',
51
+ 'black', 'white', 'magenta', 'cyan', 'r', 'g', 'b', 'y', 'k', 'w', 'm', 'c'
52
+ :return: RGBA tuple, e.g. (1.0, 0.0, 0.0, 1.0)
53
+ """
54
+ from matplotlib.colors import to_rgba
55
+
56
+ rgba = to_rgba(color_text)
57
+ if flat:
58
+ r, g, b, _ = (np.array(rgba)*255).astype(np.uint32)
59
+ falt_rgb = ((r << 16) & 0xFF0000) | \
60
+ ((g << 8) & 0x00FF00) | \
61
+ ((b << 0) & 0x0000FF)
62
+ return falt_rgb
63
+ else:
64
+ return rgba
65
+
66
+
67
+ def set_uniform(shader, content, name):
68
+ location = glGetUniformLocation(shader, name)
69
+ if location == -1:
70
+ raise ValueError(
71
+ f"Uniform '{name}' not found in shader program {shader}.")
72
+
73
+ if isinstance(content, int):
74
+ glUniform1i(location, content)
75
+ elif isinstance(content, float):
76
+ glUniform1f(location, content)
77
+ elif isinstance(content, np.ndarray):
78
+ if content.ndim == 1:
79
+ if content.shape[0] == 2:
80
+ glUniform2f(location, *content)
81
+ elif content.shape[0] == 3:
82
+ glUniform3f(location, *content)
83
+ else:
84
+ raise ValueError(
85
+ f"Unsupported 1D array size: {content.shape}.")
86
+ elif content.ndim == 2:
87
+ if content.shape == (4, 4):
88
+ glUniformMatrix4fv(location, 1, GL_FALSE,
89
+ content.T.astype(np.float32))
90
+ else:
91
+ raise ValueError(
92
+ f"Unsupported 2D array size: {content.shape}.")
93
+ else:
94
+ raise ValueError(f"Unsupported array dimension: {content.ndim}.")
95
+ else:
96
+ raise TypeError(
97
+ f"Unsupported type for uniform '{name}': {type(content)}.")
q3dviewer/utils/maths.py CHANGED
@@ -10,7 +10,6 @@ https://github.com/scomup/MathematicalRobotics.git
10
10
 
11
11
 
12
12
  import numpy as np
13
- from matplotlib.colors import to_rgba
14
13
 
15
14
 
16
15
  _epsilon_ = 1e-5
@@ -159,42 +158,6 @@ def frustum(left, right, bottom, top, near, far):
159
158
  return matrix
160
159
 
161
160
 
162
- def rainbow(scalars, scalar_min=0, scalar_max=255):
163
- range = scalar_max - scalar_min
164
- values = 1.0 - (scalars - scalar_min) / range
165
- # values = (scalars - scalar_min) / range # using inverted color
166
- colors = np.zeros([scalars.shape[0], 3], dtype=np.float32)
167
- values = np.clip(values, 0, 1)
168
-
169
- h = values * 5.0 + 1.0
170
- i = np.floor(h).astype(int)
171
- f = h - i
172
- f[np.logical_not(i % 2)] = 1 - f[np.logical_not(i % 2)]
173
- n = 1 - f
174
-
175
- # idx = i <= 1
176
- colors[i <= 1, 0] = n[i <= 1] * 255
177
- colors[i <= 1, 1] = 0
178
- colors[i <= 1, 2] = 255
179
-
180
- colors[i == 2, 0] = 0
181
- colors[i == 2, 1] = n[i == 2] * 255
182
- colors[i == 2, 2] = 255
183
-
184
- colors[i == 3, 0] = 0
185
- colors[i == 3, 1] = 255
186
- colors[i == 3, 2] = n[i == 3] * 255
187
-
188
- colors[i == 4, 0] = n[i == 4] * 255
189
- colors[i == 4, 1] = 255
190
- colors[i == 4, 2] = 0
191
-
192
- colors[i >= 5, 0] = 255
193
- colors[i >= 5, 1] = n[i >= 5] * 255
194
- colors[i >= 5, 2] = 0
195
- return colors
196
-
197
-
198
161
  def euler_to_matrix(rpy):
199
162
  roll, pitch, yaw = rpy
200
163
  Rx = np.array([[1, 0, 0],
@@ -294,27 +257,6 @@ def makeRt(T):
294
257
  return R, t
295
258
 
296
259
 
297
- def text_to_rgba(color_text, flat=False):
298
- """
299
- Convert a color text to an RGBA tuple.
300
-
301
- :param color_text: e.g. '#FF0000', '#FF0000FF', 'red', 'green', 'blue', 'yellow',
302
- 'black', 'white', 'magenta', 'cyan', 'r', 'g', 'b', 'y', 'k', 'w', 'm', 'c'
303
- :return: RGBA tuple, e.g. (1.0, 0.0, 0.0, 1.0)
304
- """
305
- rgba = to_rgba(color_text)
306
- if flat:
307
- r, g, b, _ = (np.array(rgba)*255).astype(np.uint32)
308
- falt_rgb = ((r << 16) & 0xFF0000) | \
309
- ((g << 8) & 0x00FF00) | \
310
- ((b << 0) & 0x0000FF)
311
- return falt_rgb
312
- else:
313
- return rgba
314
- # except ValueError as e:
315
- # raise ValueError(f"Invalid color text '{color_text}': {e}")
316
-
317
-
318
260
  # euler = np.array([1, 0.1, 0.1])
319
261
  # euler_angles = matrix_to_euler(euler_to_matrix(euler))
320
262
  # print("Euler Angles:", euler_angles)
@@ -3,9 +3,9 @@ Copyright 2024 Panasonic Advanced Technology Development Co.,Ltd. (Liu Yang)
3
3
  Distributed under MIT license. See LICENSE for more information.
4
4
  """
5
5
 
6
- from PySide6.QtCore import Qt, Signal
7
- from PySide6.QtGui import QPainter, QColor
8
- from PySide6.QtWidgets import QSlider
6
+ from q3dviewer.Qt.QtCore import Qt, Signal
7
+ from q3dviewer.Qt.QtGui import QPainter, QColor
8
+ from q3dviewer.Qt.QtWidgets import QSlider, QToolTip
9
9
 
10
10
 
11
11
  class RangeSlider(QSlider):
@@ -20,6 +20,10 @@ class RangeSlider(QSlider):
20
20
  self.lower_value = vmin
21
21
  self.upper_value = vmax
22
22
  self.active_handle = None
23
+ self.bar_color = QColor(200, 200, 200) # Gray bar
24
+ self.highlight_color = QColor(100, 100, 255) # Blue for selected range
25
+ self.handle_color = QColor(50, 50, 255) # Blue handles
26
+
23
27
  self.setTickPosition(QSlider.NoTicks) # Hide original ticks
24
28
  # Hide slider handle
25
29
  self.setStyleSheet("QSlider::handle { background: transparent; }")
@@ -41,35 +45,50 @@ class RangeSlider(QSlider):
41
45
  if self.active_handle == "lower":
42
46
  self.lower_value = max(
43
47
  self.minimum(), min(pos, self.upper_value - 1))
48
+ QToolTip.showText(event.globalPos(), f"Lower: {self.lower_value:.1f}")
44
49
  elif self.active_handle == "upper":
45
50
  self.upper_value = min(
46
51
  self.maximum(), max(pos, self.lower_value + 1))
52
+ QToolTip.showText(event.globalPos(), f"Upper: {self.upper_value:.1f}")
47
53
  self.rangeChanged.emit(self.lower_value, self.upper_value)
48
54
  self.update()
49
55
 
56
+ def mouseReleaseEvent(self, event):
57
+ """Override to hide tooltip when mouse stops."""
58
+ QToolTip.hideText()
59
+ super().mouseReleaseEvent(event)
60
+
61
+ def enterEvent(self, event):
62
+ """Show tooltips for lower and upper values when mouse enters."""
63
+ QToolTip.showText(self.mapToGlobal(self.rect().topLeft()),
64
+ f"Lower: {self.lower_value:.1f}, Upper: {self.upper_value:.1f}")
65
+ super().enterEvent(event)
66
+
67
+ def leaveEvent(self, event):
68
+ """Hide tooltips when mouse leaves."""
69
+ QToolTip.hideText()
70
+ super().leaveEvent(event)
71
+
50
72
  def paintEvent(self, event):
51
73
  """Override to paint custom range handles."""
52
74
  painter = QPainter(self)
53
75
 
54
76
  # Draw the range bar
55
- bar_color = QColor(200, 200, 200) # Gray bar
56
- highlight_color = QColor(100, 100, 255) # Blue for selected range
57
77
  painter.setPen(Qt.NoPen)
58
78
 
59
79
  bar_height = 6
60
80
  bar_y = self.height() // 2 - bar_height // 2
61
- painter.setBrush(bar_color)
81
+ painter.setBrush(self.bar_color)
62
82
  painter.drawRect(0, bar_y, self.width(), bar_height)
63
83
 
64
84
  # Draw the selected range
65
85
  lower_x = int(self.valueToPixelPos(self.lower_value))
66
86
  upper_x = int(self.valueToPixelPos(self.upper_value))
67
- painter.setBrush(highlight_color)
87
+ painter.setBrush(self.highlight_color)
68
88
  painter.drawRect(lower_x, bar_y, upper_x - lower_x, bar_height)
69
89
 
70
90
  # Draw the range handles
71
- handle_color = QColor(50, 50, 255) # Blue handles
72
- painter.setBrush(handle_color)
91
+ painter.setBrush(self.handle_color)
73
92
  painter.drawEllipse(lower_x - 5, bar_y - 4, 12, 12)
74
93
  painter.drawEllipse(upper_x - 5, bar_y - 4, 12, 12)
75
94
 
q3dviewer/viewer.py CHANGED
@@ -6,7 +6,7 @@ Distributed under MIT license. See LICENSE for more information.
6
6
 
7
7
  from q3dviewer.glwidget import *
8
8
  import signal
9
- from PySide6.QtWidgets import QMainWindow, QApplication, QHBoxLayout
9
+ from q3dviewer.Qt.QtWidgets import QMainWindow, QApplication, QHBoxLayout
10
10
 
11
11
 
12
12
  def handler(signal, frame):
@@ -1,25 +1,24 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q3dviewer
3
- Version: 1.1.5
3
+ Version: 1.1.6
4
4
  Summary: A library designed for quickly deploying a 3D viewer.
5
5
  Home-page: https://github.com/scomup/q3dviewer
6
6
  Author: Liu Yang
7
- License: UNKNOWN
8
- Platform: UNKNOWN
9
7
  Classifier: Programming Language :: Python :: 3
10
8
  Classifier: License :: OSI Approved :: MIT License
11
9
  Classifier: Operating System :: OS Independent
12
10
  Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy
13
+ Requires-Dist: pyside6
13
14
  Requires-Dist: PyOpenGL
15
+ Requires-Dist: meshio
16
+ Requires-Dist: pypcd4
17
+ Requires-Dist: pye57
18
+ Requires-Dist: laspy
14
19
  Requires-Dist: imageio
15
20
  Requires-Dist: imageio[ffmpeg]
16
- Requires-Dist: laspy
17
21
  Requires-Dist: matplotlib
18
- Requires-Dist: meshio
19
- Requires-Dist: numpy
20
- Requires-Dist: pye57
21
- Requires-Dist: pypcd4
22
- Requires-Dist: pyside6
23
22
 
24
23
 
25
24
  ![q3dviewer Logo](imgs/logo.png)
@@ -172,7 +171,7 @@ def main():
172
171
 
173
172
  # Create a viewer
174
173
  viewer = q3d.Viewer(name='example')
175
-
174
+
176
175
  # Add items to the viewer
177
176
  viewer.add_items({
178
177
  'grid': grid_item,
@@ -234,4 +233,3 @@ class YourItem(q3d.BaseItem):
234
233
  ```
235
234
 
236
235
  Enjoy using `q3dviewer`!
237
-
@@ -0,0 +1,49 @@
1
+ q3dviewer/__init__.py,sha256=cjyfUE5zK6xohDGDQIWfb0DKkWChVznBd7CrVLg7whQ,376
2
+ q3dviewer/base_glwidget.py,sha256=6Z5rINQ1Y9KqtpBexr0hMX66pNTh6qvovlb7fJe5ZGM,12303
3
+ q3dviewer/base_item.py,sha256=63MarHyoWszPL40ox-vPoOAQ1N4ypekOjoRARdPik-E,1755
4
+ q3dviewer/basic_window.py,sha256=CFErOPRMysFcCqq3vhDsQ-xZzLArO3m1yABCTIhq5do,7946
5
+ q3dviewer/cloud_viewer.py,sha256=IxxrB6Sl6aPCr9P9QzKHGkMcDP_DjsBWbkmIbsAoIM4,2358
6
+ q3dviewer/gau_io.py,sha256=S6NmqL5vSMgHVxKR-eu4CWCqgZeWBJKYRoOMAwr8Xbo,5890
7
+ q3dviewer/glwidget.py,sha256=pkMQxPXNxVWp_sZUFX2r4IHuw_So9ok5e-ZdvBhArFQ,4631
8
+ q3dviewer/utils.py,sha256=evF0d-v17hbTmquC24fmMIp9CsXpUnSQZr4MVy2sfao,2426
9
+ q3dviewer/viewer.py,sha256=odDtrieM5M-8C6XFrn414x0P6vaucm0UXU1FmRJ2Um4,2522
10
+ q3dviewer/Qt/__init__.py,sha256=CcwS6oSXBXTMr58JNbRNYcPMVubDD2jiPtJ55DoLm8o,2199
11
+ q3dviewer/custom_items/__init__.py,sha256=19z_BFXJEm8j31WqREICN31fiFcaIeUqvfo39d02vbk,509
12
+ q3dviewer/custom_items/axis_item.py,sha256=-WM2urosqV847zpTpOtxdLjb7y9NJqFCH13qqodcCTg,2572
13
+ q3dviewer/custom_items/camera_frame_item.py,sha256=VBsr3Avly_YWXViIh4DJkGc_HJt227GeOYLpGtbYTOw,5605
14
+ q3dviewer/custom_items/cloud_io_item.py,sha256=E3Qyc4nuVP-MQAff4zII9JB-xQjVRsviATpqvpLQveM,3507
15
+ q3dviewer/custom_items/cloud_item.py,sha256=mVJ4WW1q-2vFnLISzfNkP_D0G9mOe4jD5rMQhhn4G58,12968
16
+ q3dviewer/custom_items/frame_item.py,sha256=bUzww3tSDah0JZeqtU6_cYHhhTVWzXhJVMcAa5pCXHI,7458
17
+ q3dviewer/custom_items/gaussian_item.py,sha256=JMubpahkTPh0E8ShL3FLTahv0e35ODzjgK5K1i0YXSU,9884
18
+ q3dviewer/custom_items/grid_item.py,sha256=LDB_MYACoxld-xvz01_MfAf12vLcRkH7R_WtGHHdSgk,4945
19
+ q3dviewer/custom_items/image_item.py,sha256=k7HNTqdL2ckTbxMx7A7eKaP4aksZ85-pBjNdbpm6PXM,5355
20
+ q3dviewer/custom_items/line_item.py,sha256=rel-lx8AgjDY7qyIecHxHQZzaswRn2ZTiOIjB_0Mrqo,4444
21
+ q3dviewer/custom_items/text_item.py,sha256=VdmoCgXAfqN58fMKydqrdnJHCT53VelRiv_88X9aCfQ,2185
22
+ q3dviewer/custom_items/trajectory_item.py,sha256=uoKQSrTs_m_m1M8iNAm3peiXnZ9uVPsYQLYas3Gksjg,2754
23
+ q3dviewer/shaders/cloud_frag.glsl,sha256=tbCsDUp9YlPe0hRWlFS724SH6TtMeLO-GVYROzEElZg,609
24
+ q3dviewer/shaders/cloud_vert.glsl,sha256=Vxgw-Zrr0knAK0z4qMXKML6IC4EbffKMwYN2TMXROoI,2117
25
+ q3dviewer/shaders/gau_frag.glsl,sha256=5_UY84tWDts59bxP8x4I-wgnzY8aGeGuo28wX--LW7E,975
26
+ q3dviewer/shaders/gau_prep.glsl,sha256=eCT9nm65uz32w8NaDjeGKhyAZh42Aea-QTwr3yQVr9U,7218
27
+ q3dviewer/shaders/gau_vert.glsl,sha256=NNbVhv_JyqZDK9iXAyBAcIHAtim7G9yWbC9IaUfTL1w,1666
28
+ q3dviewer/shaders/sort_by_key.glsl,sha256=CA2zOcbyDGYAJSJEUvgjUqNshg9NAehf8ipL3Jsv4qE,1097
29
+ q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
30
+ q3dviewer/tools/cloud_viewer.py,sha256=-yKVWQb-UWpP7h3khR3dipT_X8XLLL6JllGZJ1vaOM4,3877
31
+ q3dviewer/tools/example_viewer.py,sha256=sedL18GU3bTTjVJBREPVJ5hTLfSDFq_j91E4qXnG8TU,964
32
+ q3dviewer/tools/film_maker.py,sha256=CXsI2SocgnQProIWKJ6lvRXtFv4DoO-rm6YNfweAJmw,16678
33
+ q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
34
+ q3dviewer/tools/lidar_calib.py,sha256=hHnsSaQh_Pkdh8tPntt0MgEW26nQyAdC_HQHq4I3sw8,10562
35
+ q3dviewer/tools/lidar_cam_calib.py,sha256=XnP3tdtav7OiMp88g88QsiNQToUJKCSP_BXTiIeTEms,11280
36
+ q3dviewer/tools/ros_viewer.py,sha256=ARB3I5wohY3maP8dCu0O0hxObd6JFKuK2y7AApVgMWA,2551
37
+ q3dviewer/utils/__init__.py,sha256=dwTNAAebTiKY4ygv2G1O-w6-TbJnmnNVO2UfJXvJhaQ,107
38
+ q3dviewer/utils/cloud_io.py,sha256=xarfYakY0zgKwvZkgKSPO6b4DEo42hsq3mcvCbK64yg,12134
39
+ q3dviewer/utils/convert_ros_msg.py,sha256=sAoQfy3qLQKsIArBAVm8H--wlQXOcmkKK3-Ox9UCcrc,1686
40
+ q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,1435
41
+ q3dviewer/utils/helpers.py,sha256=SqR4YTQZi13FKbkVUYgodXce1JJ_YmrHEIRkUmnIUas,3085
42
+ q3dviewer/utils/maths.py,sha256=zHaPtvVZIuo8xepIXCMeSL9tpx8FahUrq0l4K1oXrBk,8834
43
+ q3dviewer/utils/range_slider.py,sha256=9djTxuzmzH54DgSwAljRpLGjsrIJ0hTxhaxFjPxsk8g,4007
44
+ q3dviewer-1.1.6.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
45
+ q3dviewer-1.1.6.dist-info/METADATA,sha256=OYd2NVqjqX9VkRGPQAsCzOtydm1cl9swhfbWEh6TpZ0,7974
46
+ q3dviewer-1.1.6.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
47
+ q3dviewer-1.1.6.dist-info/entry_points.txt,sha256=aeUdGH7UIgMZEMFUc-0xPZWspY95GoPdZcZuLceq85g,361
48
+ q3dviewer-1.1.6.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
49
+ q3dviewer-1.1.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: setuptools (75.3.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -6,4 +6,3 @@ lidar_calib = q3dviewer.tools.lidar_calib:main
6
6
  lidar_cam_calib = q3dviewer.tools.lidar_cam_calib:main
7
7
  mesh_viewer = q3dviewer.tools.mesh_viewer:main
8
8
  ros_viewer = q3dviewer.tools.ros_viewer:main
9
-
@@ -1,47 +0,0 @@
1
- q3dviewer/__init__.py,sha256=rP5XX_x8g7hxIMqNHlU89BN4dt5MSvoYYwip68fCmhc,173
2
- q3dviewer/base_glwidget.py,sha256=yQb4ckj4ldmiFoKL_TdZAqZNeBnMeSRDhLbMaruM3nk,12298
3
- q3dviewer/base_item.py,sha256=lzb04oRaS4rRJrAP6C1Bu4ugK237FgupMTB97zjNVFw,1768
4
- q3dviewer/basic_window.py,sha256=CFErOPRMysFcCqq3vhDsQ-xZzLArO3m1yABCTIhq5do,7946
5
- q3dviewer/cloud_viewer.py,sha256=IxxrB6Sl6aPCr9P9QzKHGkMcDP_DjsBWbkmIbsAoIM4,2358
6
- q3dviewer/gau_io.py,sha256=S6NmqL5vSMgHVxKR-eu4CWCqgZeWBJKYRoOMAwr8Xbo,5890
7
- q3dviewer/glwidget.py,sha256=2scii9IeY3ion12lFgWtGXO9JrlUD3tfp3zXt7gnFoQ,4689
8
- q3dviewer/utils.py,sha256=evF0d-v17hbTmquC24fmMIp9CsXpUnSQZr4MVy2sfao,2426
9
- q3dviewer/viewer.py,sha256=LH1INLFhi6pRjzazzQJ0AWT4hgyXI6GnmqoJFUwUZVE,2517
10
- q3dviewer/custom_items/__init__.py,sha256=gOiAxdjDaAnFL8YbqSEWWWOwUrJfvzP9JLR34sCB9-4,434
11
- q3dviewer/custom_items/axis_item.py,sha256=PTBSf5DmQI8ieSinYjY_aC7P8q1nzE-2Vc2GNd1O3Os,2568
12
- q3dviewer/custom_items/camera_frame_item.py,sha256=VBsr3Avly_YWXViIh4DJkGc_HJt227GeOYLpGtbYTOw,5605
13
- q3dviewer/custom_items/cloud_io_item.py,sha256=l7FGKb1s3kEFw1GT8Bro5oJfu4reuvunHJkM1pmpxz4,3038
14
- q3dviewer/custom_items/cloud_item.py,sha256=JtjehxPYuzypVg_8ENfZvN7yEVO-Ac7GE8Dt3jzP6yk,12763
15
- q3dviewer/custom_items/frame_item.py,sha256=9g4SxIGZCWFWaX5Xfd9G-P63VlonysxEC239lk7dRRg,7408
16
- q3dviewer/custom_items/gaussian_item.py,sha256=CZoXMmj2JPFfMqu7v4q4dLUI2cg_WfE1DHWGXjEYn6M,9869
17
- q3dviewer/custom_items/grid_item.py,sha256=58QUKli_9NEtYchulZt5Xhqk6k2DaL5RlEMaYyt7MSE,4965
18
- q3dviewer/custom_items/image_item.py,sha256=3FYAVlNLEILKZplkt2wbL8y16ke124GmwxcSmWmJY8Q,5357
19
- q3dviewer/custom_items/line_item.py,sha256=np8sORS5kZFWptOUa_Vlq1p7b9rMK3CpGsBd77Qpo2M,4445
20
- q3dviewer/custom_items/text_item.py,sha256=G3PPpN_0yjUMWJKvNG5QFgqxmE6LUEW5VIUDdi3kwuk,2314
21
- q3dviewer/custom_items/trajectory_item.py,sha256=uoKQSrTs_m_m1M8iNAm3peiXnZ9uVPsYQLYas3Gksjg,2754
22
- q3dviewer/shaders/cloud_frag.glsl,sha256=tbCsDUp9YlPe0hRWlFS724SH6TtMeLO-GVYROzEElZg,609
23
- q3dviewer/shaders/cloud_vert.glsl,sha256=Vxgw-Zrr0knAK0z4qMXKML6IC4EbffKMwYN2TMXROoI,2117
24
- q3dviewer/shaders/gau_frag.glsl,sha256=5_UY84tWDts59bxP8x4I-wgnzY8aGeGuo28wX--LW7E,975
25
- q3dviewer/shaders/gau_prep.glsl,sha256=eCT9nm65uz32w8NaDjeGKhyAZh42Aea-QTwr3yQVr9U,7218
26
- q3dviewer/shaders/gau_vert.glsl,sha256=NNbVhv_JyqZDK9iXAyBAcIHAtim7G9yWbC9IaUfTL1w,1666
27
- q3dviewer/shaders/sort_by_key.glsl,sha256=CA2zOcbyDGYAJSJEUvgjUqNshg9NAehf8ipL3Jsv4qE,1097
28
- q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
29
- q3dviewer/tools/cloud_viewer.py,sha256=10f2LSWpmsXzxrGobXw188doVjJbgBfPoqZPUi35EtI,3867
30
- q3dviewer/tools/example_viewer.py,sha256=yeVXT0k4-h1vTLKnGzWADZD3our6XUaYUTy0p5daTkE,959
31
- q3dviewer/tools/film_maker.py,sha256=w97LMMmSpjTOMdG2j0ucK2kDoU3k__746jRVh2fJfvc,16598
32
- q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
33
- q3dviewer/tools/lidar_calib.py,sha256=M01bGg2mT8LwVcYybolr4UW_UUaR-f-BFciEHtjeK-w,10488
34
- q3dviewer/tools/lidar_cam_calib.py,sha256=SYNLDvi15MX7Q3aGn771fvu1cES9xeXgP0_WmDq33w4,11200
35
- q3dviewer/tools/ros_viewer.py,sha256=ARB3I5wohY3maP8dCu0O0hxObd6JFKuK2y7AApVgMWA,2551
36
- q3dviewer/utils/__init__.py,sha256=irm8Z_bT8l9kzhoMlds2Dal8g4iw4vjmqNPZSs4W6e0,157
37
- q3dviewer/utils/cloud_io.py,sha256=xnsT3VEKS435BE1DwhciRHicwzuC-8-JASkImT8pKNk,11681
38
- q3dviewer/utils/convert_ros_msg.py,sha256=sAoQfy3qLQKsIArBAVm8H--wlQXOcmkKK3-Ox9UCcrc,1686
39
- q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,1435
40
- q3dviewer/utils/maths.py,sha256=tHx2q_qAFPQQoFJbnwB0Ts-xtEibeGAhJrMHOH6aCPk,10575
41
- q3dviewer/utils/range_slider.py,sha256=jZJQL-uQgnpgLvtYSWpKTrJlLkt3aqNpaRQAePEpNd0,3174
42
- q3dviewer-1.1.5.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
43
- q3dviewer-1.1.5.dist-info/METADATA,sha256=6DZkBF6Jsghr4qu0K2Wp-gzjP8qoflKCvSk6qi2EoP4,7984
44
- q3dviewer-1.1.5.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
45
- q3dviewer-1.1.5.dist-info/entry_points.txt,sha256=EOjker7XYaBk70ffvNB_knPcfA33Bnlg21ZjEeM1EyI,362
46
- q3dviewer-1.1.5.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
47
- q3dviewer-1.1.5.dist-info/RECORD,,