q3dviewer 1.2.2__py3-none-any.whl → 1.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,39 +7,30 @@ 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 q3dviewer.Qt.QtWidgets import QVBoxLayout, QProgressBar, QDialog, QLabel
10
+ from q3dviewer.Qt.QtWidgets import QVBoxLayout, QDialog, QLabel
11
11
  from q3dviewer.Qt.QtCore import QThread, Signal, Qt
12
- from q3dviewer.Qt.QtGui import QKeyEvent
13
12
  from q3dviewer import GLWidget
13
+ from q3dviewer.utils.helpers import get_version
14
14
 
15
-
16
- class ProgressDialog(QDialog):
15
+ class ProgressWindow(QDialog):
17
16
  def __init__(self, parent=None):
18
17
  super().__init__(parent)
19
- self.setWindowTitle("Loading Cloud File")
18
+ self.setWindowTitle("Loading")
20
19
  self.setModal(True)
21
- self.progress_bar = QProgressBar(self)
22
- self.file_label = QLabel(self)
20
+ self.setMinimumWidth(400)
21
+ self.label = QLabel(self)
22
+ self.label.setAlignment(Qt.AlignCenter)
23
23
  layout = QVBoxLayout()
24
- layout.addWidget(self.file_label)
25
- layout.addWidget(self.progress_bar)
24
+ layout.addWidget(self.label)
26
25
  self.setLayout(layout)
27
26
 
28
- def set_value(self, value):
29
- self.progress_bar.setValue(value)
30
-
31
- def set_file_name(self, file_name):
32
- self.file_label.setText(f"Loading: {file_name}")
33
-
34
- def closeEvent(self, event):
35
- if self.parent().progress_thread and self.parent().progress_thread.isRunning():
36
- event.ignore()
37
- else:
38
- event.accept()
27
+ def update_progress(self, current, total, file_name):
28
+ text = f"[{current}/{total}] loading file: {file_name}"
29
+ self.label.setText(text)
39
30
 
40
31
 
41
32
  class FileLoaderThread(QThread):
42
- progress = Signal(int)
33
+ progress = Signal(int, int, str) # current, total, filename
43
34
  finished = Signal()
44
35
 
45
36
  def __init__(self, viewer, files):
@@ -50,25 +41,22 @@ class FileLoaderThread(QThread):
50
41
  def run(self):
51
42
  cloud_item = self.viewer['cloud']
52
43
  mesh_item = self.viewer['mesh']
44
+ total = len(self.files)
53
45
  for i, url in enumerate(self.files):
54
46
  # if the file is a mesh file, use mesh_item to load
55
47
  file_path = url.toLocalFile()
56
- file_path = url.toLocalFile()
57
- self.viewer.progress_dialog.set_file_name(file_path)
48
+ import os
49
+ file_name = os.path.basename(file_path)
50
+ self.progress.emit(i + 1, total, file_name)
51
+
58
52
  if url.toLocalFile().lower().endswith(('.stl')):
59
53
  from q3dviewer.utils.cloud_io import load_stl
60
- verts, faces = load_stl(file_path)
61
- # create colors, N, array
62
- color = np.zeros((verts.shape[0],), dtype=np.uint32)
63
- # random uint32 colors in IRGB format
64
- color = np.random.randint(0, 0xFFFFFFFF, size=(verts.shape[0],), dtype=np.uint32)
65
- mesh_item.set_data(verts=verts, faces=faces, colors=color)
66
- break
54
+ mesh = load_stl(file_path)
55
+ mesh_item.set_data(mesh)
67
56
  else:
68
57
  cloud = cloud_item.load(file_path, append=(i > 0))
69
58
  center = np.nanmean(cloud['xyz'].astype(np.float64), axis=0)
70
59
  self.viewer.glwidget.set_cam_position(center=center)
71
- self.progress.emit(int((i + 1) / len(self.files) * 100))
72
60
  self.finished.emit()
73
61
 
74
62
 
@@ -135,20 +123,19 @@ class CloudViewer(q3d.Viewer):
135
123
  """
136
124
  Overwrite the drop event to open the cloud file.
137
125
  """
138
- self.progress_dialog = ProgressDialog(self)
139
- self.progress_dialog.show()
126
+ self.progress_window = ProgressWindow(self)
127
+ self.progress_window.show()
140
128
  files = event.mimeData().urls()
141
129
  self.progress_thread = FileLoaderThread(self, files)
142
- self['cloud'].load(files[0].toLocalFile(), append=False)
143
130
  self.progress_thread.progress.connect(self.file_loading_progress)
144
131
  self.progress_thread.finished.connect(self.file_loading_finished)
145
132
  self.progress_thread.start()
146
133
 
147
- def file_loading_progress(self, value):
148
- self.progress_dialog.set_value(value)
134
+ def file_loading_progress(self, current, total, file_name):
135
+ self.progress_window.update_progress(current, total, file_name)
149
136
 
150
137
  def file_loading_finished(self):
151
- self.progress_dialog.close()
138
+ self.progress_window.close()
152
139
 
153
140
  def open_cloud_file(self, file, append=False):
154
141
  cloud_item = self['cloud']
@@ -159,27 +146,50 @@ class CloudViewer(q3d.Viewer):
159
146
  center = np.nanmean(cloud['xyz'].astype(np.float64), axis=0)
160
147
  self.glwidget.set_cam_position(center=center)
161
148
 
162
- # print a quick help message
149
+ # print a quick help message using rich
163
150
  def print_help():
164
- # ANSI color codes
165
- GREEN = '\033[92m'
166
- BLUE = '\033[94m'
167
- BOLD = '\033[1m'
168
- END = '\033[0m'
151
+ from rich.console import Console
152
+ from rich.panel import Panel
153
+ from rich.table import Table
154
+ from rich.text import Text
155
+
156
+ console = Console()
157
+
158
+ # Create a table for better organization
159
+ table = Table(show_header=False, box=None, padding=(0, 2))
160
+ table.add_column(style="bold cyan", width=30)
161
+ table.add_column(style="white")
162
+
163
+ # File loading section
164
+ table.add_row("📁 Load Files","Drag and drop files into the viewer")
165
+ table.add_row("","[dim]• Point clouds: .pcd, .ply, .las, .e57[/dim]")
166
+ table.add_row("","[dim]• Mesh files: .stl[/dim]")
167
+ table.add_row("", "")
168
+
169
+ # Measurement section
170
+ table.add_row("📏 Measure Distance", "Interactive point measurement")
171
+ table.add_row("","[dim]• Ctrl + Left Click: Add measurement point[/dim]")
172
+ table.add_row("","[dim]• Ctrl + Right Click: Remove last point[/dim]")
173
+ table.add_row("","[dim]• Total distance displayed automatically[/dim]")
174
+ table.add_row("", "")
175
+
176
+ # Camera controls
177
+ table.add_row("🎥 Camera Controls","Navigate the 3D scene")
178
+ table.add_row("","[dim]• Double Click: Set camera center to point[/dim]")
179
+ table.add_row("","[dim]• Right Drag: Rotate view[/dim]")
180
+ table.add_row("","[dim]• Left Drag: Pan view[/dim]")
181
+ table.add_row("","[dim]• Mouse Wheel: Zoom in/out[/dim]")
182
+ table.add_row("", "")
183
+
184
+ # Settings section
185
+ table.add_row("⚙️ Settings","Press [bold green]'M'[/bold green] to open settings window")
186
+ table.add_row("","[dim]Adjust visualization properties[/dim]")
169
187
 
170
- help_msg = f"""
171
- {BOLD}Cloud Viewer Help:{END}
172
- {GREEN}• Drag and drop cloud files into the viewer to load them.{END}
173
- {BLUE}- support .pcd, .ply, .las, .e57, for point clouds.{END}
174
- {BLUE}- support .stl for mesh files.{END}
175
- {GREEN}• Measure distance between points:{END}
176
- {BLUE}- Hold Ctrl and left-click to select points on the cloud.{END}
177
- {BLUE}- Hold Ctrl and right-click to remove the last selected point.{END}
178
- {BLUE}- The total distance between selected points will be displayed.{END}
179
- {GREEN}• Press 'M' to open the settings window.{END}
180
- {BLUE}- Use the settings window to adjust item properties.{END}
181
- """
182
- print(help_msg)
188
+ # Print title and table without border
189
+ console.print()
190
+ console.print(f"[bold magenta]☁️ Cloud Viewer ({get_version()}) Help[/bold magenta]\n")
191
+ console.print(table)
192
+ console.print()
183
193
 
184
194
  def main():
185
195
  print_help()
@@ -196,7 +206,7 @@ def main():
196
206
  marker_item = q3d.Text3DItem() # Changed from CloudItem to Text3DItem
197
207
  text_item = q3d.Text2DItem(pos=(20, 40), text="", color='lime', size=16)
198
208
  text_item.disable_setting()
199
- mesh_item = q3d.MeshItem() # Added MeshIOItem for mesh support
209
+ mesh_item = q3d.StaticMeshItem()
200
210
 
201
211
  viewer.add_items(
202
212
  {'marker': marker_item,
@@ -12,7 +12,7 @@ from q3dviewer.Qt.QtCore import QTimer
12
12
  from q3dviewer.Qt.QtGui import QKeyEvent
13
13
  from q3dviewer.Qt import QtCore
14
14
  from q3dviewer import GLWidget
15
- from q3dviewer.tools.cloud_viewer import ProgressDialog, FileLoaderThread
15
+ from q3dviewer.tools.cloud_viewer import FileLoaderThread, ProgressWindow
16
16
 
17
17
  import imageio.v2 as imageio
18
18
  import os
@@ -386,20 +386,19 @@ class CMMViewer(q3d.Viewer):
386
386
  """
387
387
  Overwrite the drop event to open the cloud file.
388
388
  """
389
- self.progress_dialog = ProgressDialog(self)
390
- self.progress_dialog.show()
389
+ self.progress_window = ProgressWindow(self)
390
+ self.progress_window.show()
391
391
  files = event.mimeData().urls()
392
392
  self.progress_thread = FileLoaderThread(self, files)
393
- self['cloud'].load(files[0].toLocalFile(), append=False)
394
393
  self.progress_thread.progress.connect(self.file_loading_progress)
395
394
  self.progress_thread.finished.connect(self.file_loading_finished)
396
395
  self.progress_thread.start()
397
396
 
398
- def file_loading_progress(self, value):
399
- self.progress_dialog.set_value(value)
397
+ def file_loading_progress(self, current, total, file_name):
398
+ self.progress_window.update_progress(current, total, file_name)
400
399
 
401
400
  def file_loading_finished(self):
402
- self.progress_dialog.close()
401
+ self.progress_window.close()
403
402
 
404
403
  def open_cloud_file(self, file, append=False):
405
404
  cloud_item = self['cloud']
@@ -417,7 +416,7 @@ def main():
417
416
  args = parser.parse_args()
418
417
  app = q3d.QApplication(['Film Maker'])
419
418
  viewer = CMMViewer(name='Film Maker', update_interval=30)
420
- cloud_item = q3d.CloudIOItem(size=1, point_type='SPHERE', alpha=0.5, depth_test=True)
419
+ cloud_item = q3d.CloudIOItem(size=1, point_type='SPHERE', alpha=0.5)
421
420
  grid_item = q3d.GridItem(size=1000, spacing=20)
422
421
 
423
422
  viewer.add_items(
@@ -7,25 +7,52 @@ import numpy as np
7
7
 
8
8
 
9
9
  def load_stl(file_path):
10
- from stl import mesh as stlmesh
11
- m = stlmesh.Mesh.from_file(file_path)
12
- verts = m.vectors.reshape(-1, 3).astype(np.float32)
13
- faces = np.arange(len(verts), dtype=np.uint32).reshape(-1, 3)
14
- return verts, faces
15
-
16
-
17
- def save_stl(verts, faces, save_path):
18
- """Save the generated mesh as an STL file."""
19
- from stl import mesh as stlmesh
20
- from stl import Mode
21
- verts = np.asarray(verts, dtype=np.float32)
22
- faces = np.asarray(faces, dtype=np.uint32)
23
- # Create the mesh
24
- m = stlmesh.Mesh(np.zeros(faces.shape[0], dtype=stlmesh.Mesh.dtype))
25
- m.vectors[:] = verts[faces].astype(np.float32)
26
- # Save to file
27
- m.save(save_path, mode=Mode.BINARY)
28
-
10
+ import meshio
11
+ mesh = meshio.read(file_path)
12
+ # meshio returns cells as a list of (cell_type, cell_data) tuples
13
+ # For STL, we expect 'triangle' cells
14
+ vertices = mesh.points.astype(np.float32)
15
+
16
+ # Find triangle cells
17
+ triangles = None
18
+ for cell_block in mesh.cells:
19
+ if cell_block.type == 'triangle':
20
+ triangles = cell_block.data
21
+ break
22
+
23
+ if triangles is None:
24
+ raise ValueError(f"No triangle cells found in STL file: {file_path}")
25
+
26
+ # Convert indexed triangles to flat vertex array (N*3, 3)
27
+ faces = vertices[triangles.flatten()].astype(np.float32)
28
+ return faces
29
+
30
+
31
+ def save_stl(faces, save_path, binary=True):
32
+ import meshio
33
+ faces = np.asarray(faces, dtype=np.float32)
34
+ if faces.shape[0] % 3 != 0:
35
+ raise ValueError(f"Invalid faces shape: {faces.shape}, must be (N*3, 3)")
36
+
37
+ # Reshape to (num_triangles, 3, 3)
38
+ num_triangles = faces.shape[0] // 3
39
+ triangles = faces.reshape(num_triangles, 3, 3)
40
+
41
+ # Get unique vertices and create index array
42
+ vertices, indices = np.unique(triangles.reshape(-1, 3), axis=0, return_inverse=True)
43
+ triangle_indices = indices.reshape(num_triangles, 3)
44
+
45
+ # Create meshio mesh object
46
+ mesh = meshio.Mesh(
47
+ points=vertices,
48
+ cells=[("triangle", triangle_indices)]
49
+ )
50
+ # meshio automatically saves STL as binary by default
51
+ # Use file_format="stl-ascii" for ASCII format
52
+ if binary:
53
+ mesh.write(save_path, binary=True)
54
+ else:
55
+ mesh.write(save_path, binary=False)
29
56
 
30
57
  def save_ply(cloud, save_path):
31
58
  import meshio
@@ -7,6 +7,18 @@ import numpy as np
7
7
  from OpenGL.GL import *
8
8
 
9
9
 
10
+ def get_version():
11
+ """
12
+ Get the version of q3dviewer package.
13
+ """
14
+ try:
15
+ from importlib.metadata import version
16
+ return version('q3dviewer')
17
+ except Exception:
18
+ # Fallback if package is not installed
19
+ return 'unknown'
20
+
21
+
10
22
  def rainbow(scalars, scalar_min=0, scalar_max=255):
11
23
  range = scalar_max - scalar_min
12
24
  values = 1.0 - (scalars - scalar_min) / range
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q3dviewer
3
- Version: 1.2.2
3
+ Version: 1.2.4
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
7
+ Author-email: liu.yang@jp.panasonic.com
8
+ License: MIT
8
9
  Platform: UNKNOWN
9
10
  Classifier: Programming Language :: Python :: 3
10
11
  Classifier: License :: OSI Approved :: MIT License
@@ -17,7 +18,6 @@ Requires-Dist: laspy
17
18
  Requires-Dist: matplotlib
18
19
  Requires-Dist: meshio
19
20
  Requires-Dist: numpy
20
- Requires-Dist: numpy-stl
21
21
  Requires-Dist: pye57
22
22
  Requires-Dist: pypcd4
23
23
  Requires-Dist: pyside6
@@ -75,22 +75,34 @@ python3 -m q3dviewer.tools.cloud_viewer
75
75
  ```
76
76
 
77
77
  **Basic Operations**
78
- * Load files: Drag and drop point cloud files onto the window (multiple files are OK).
79
- * `M` key: Display the visualization settings screen for point clouds, background color, etc.
80
- * `Left mouse button` & `W, A, S, D` keys: Move the viewpoint on the horizontal plane.
81
- * `Z, X` keys: Move in the direction the screen is facing.
82
- * `Right mouse button` & `Arrow` keys: Rotate the viewpoint while keeping the screen center unchanged.
83
- * `Shift` + `Right mouse button` & `Arrow` keys: Rotate the viewpoint while keeping the camera position unchanged.
78
+
79
+ 📁 **Load Files** - Drag and drop files into the viewer
80
+ * Point clouds: .pcd, .ply, .las, .e57
81
+ * Mesh files: .stl
82
+
83
+ 📏 **Measure Distance** - Interactive point measurement
84
+ * `Ctrl + Left Click`: Add measurement point
85
+ * `Ctrl + Right Click`: Remove last point
86
+ * Total distance displayed automatically
87
+
88
+ 🎥 **Camera Controls** - Navigate the 3D scene
89
+ * `Double Click`: Set camera center to point
90
+ * `Right Drag`: Rotate view
91
+ * `Left Drag`: Pan view
92
+ * `Mouse Wheel`: Zoom in/out
93
+
94
+ ⚙️ **Settings** - Press `M` to open settings window
95
+ * Adjust visualization properties
84
96
 
85
97
  For example, you can download and view point clouds of Tokyo in LAS format from the following link:
86
98
 
87
99
  [Tokyo Point Clouds](https://www.geospatial.jp/ckan/dataset/tokyopc-23ku-2024/resource/7807d6d1-29f3-4b36-b0c8-f7aa0ea2cff3)
88
100
 
89
- ![Cloud Viewer Screenshot](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149168/03c981c6-1aec-e5b9-4536-e07e1e56ff29.png)
101
+ ![Cloud Viewer Screenshot](imgs/tokyo.png)
90
102
 
91
- Press `M` on your keyboard to display a menu on the screen, where you can modify visualization settings for each item. For example, you can adjust various settings such as shape, size, color, and transparency for `CloudItem`.
103
+ **Mesh Support** - Starting from version 1.2.4, mesh files (.stl) are now supported.
92
104
 
93
- ![Cloud Viewer Settings](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149168/deeb996a-e419-58f4-6bc2-535099b1b73a.png)
105
+ ![Screenshot from 2026-02-04 18-32-04.png](imgs/mesh.png)
94
106
 
95
107
  ### 2. ROS Viewer
96
108
 
@@ -1,10 +1,10 @@
1
- q3dviewer/__init__.py,sha256=cjyfUE5zK6xohDGDQIWfb0DKkWChVznBd7CrVLg7whQ,376
1
+ q3dviewer/__init__.py,sha256=Nz48lhIxsGYMLvhOLQT0AXhn6d64wA4hdIz4d0qsVLc,172
2
2
  q3dviewer/base_glwidget.py,sha256=QxAuZzQSBbzTwpHHqYpiM-Jqv41E4YJmFG4KRF-HruY,15274
3
3
  q3dviewer/base_item.py,sha256=63MarHyoWszPL40ox-vPoOAQ1N4ypekOjoRARdPik-E,1755
4
- q3dviewer/glwidget.py,sha256=EmrxPtVQ8RdPK5INKMlpKpVfX0KCfjSKRdGf4cSB1f0,5405
4
+ q3dviewer/glwidget.py,sha256=taewDTQUqmKOrDYz_ygghu00dlCnWzFRpDnEaTG25pA,6390
5
5
  q3dviewer/viewer.py,sha256=Vq3ucDlBcBBoiVVGmqG1sRjhLePl50heblx6wJpsc1A,2603
6
6
  q3dviewer/Qt/__init__.py,sha256=VJj7Ge6N_81__T9eHFl_YQpa1HyQrlLhMqC_9pUOYtc,2233
7
- q3dviewer/custom_items/__init__.py,sha256=kaaf84wOObfybJ8a12FqPMeg8ImTJWggA6g5nvpY2YY,621
7
+ q3dviewer/custom_items/__init__.py,sha256=BXZzyOnwwB81pthx39n6issyroaxUxpCJPeW2U-TaWU,689
8
8
  q3dviewer/custom_items/axis_item.py,sha256=-WM2urosqV847zpTpOtxdLjb7y9NJqFCH13qqodcCTg,2572
9
9
  q3dviewer/custom_items/cloud_io_item.py,sha256=Haz-SOUUCPDSHgmKyyyFfP7LXBSEiN4r8xmchQwCm-k,4721
10
10
  q3dviewer/custom_items/cloud_item.py,sha256=UzpkWiMYcX8kEndmRV1ScysFfOvElaKo60KV-uEO2A4,13484
@@ -13,35 +13,39 @@ q3dviewer/custom_items/gaussian_item.py,sha256=JMubpahkTPh0E8ShL3FLTahv0e35ODzjg
13
13
  q3dviewer/custom_items/grid_item.py,sha256=LDB_MYACoxld-xvz01_MfAf12vLcRkH7R_WtGHHdSgk,4945
14
14
  q3dviewer/custom_items/image_item.py,sha256=k7HNTqdL2ckTbxMx7A7eKaP4aksZ85-pBjNdbpm6PXM,5355
15
15
  q3dviewer/custom_items/line_item.py,sha256=rel-lx8AgjDY7qyIecHxHQZzaswRn2ZTiOIjB_0Mrqo,4444
16
- q3dviewer/custom_items/mesh_item.py,sha256=Ds3GyYzvFF5VpjG-_LU9SNZiBoLmztCZrkcalEMjub8,17890
16
+ q3dviewer/custom_items/mesh_item.py,sha256=L8-EoiJMH8lXmSdLOFYQSF9biODzSC616AMY6KgVGMk,19807
17
+ q3dviewer/custom_items/static_mesh_item.py,sha256=MQwlEMuYX0wB5odmeiw1nsBhciWs1jcauUvcWRDVj4Q,12882
17
18
  q3dviewer/custom_items/text3d_item.py,sha256=DYBPXnCmMEzWDE1y523YsWSl91taXAdu0kdnhUcwE4A,5524
18
19
  q3dviewer/custom_items/text_item.py,sha256=toeGjBu7RtT8CMUuaDWnmXPnA1UKHhnCzUNeonGczSo,2703
19
20
  q3dviewer/shaders/cloud_frag.glsl,sha256=psKVt9qI6BW0bCqOk4lcKqUd6XgYGtdFigyN9OdYSNI,609
20
- q3dviewer/shaders/cloud_vert.glsl,sha256=gKI6EJrzX5ga2W2yjU6x7Wjz7Cu2Y-wrPl4g10RfTLM,2376
21
+ q3dviewer/shaders/cloud_vert.glsl,sha256=7tNkdx0iuoq1sG3YZ1UuF2JOhEohcodZ363WUV2B2Q4,2370
21
22
  q3dviewer/shaders/gau_frag.glsl,sha256=vWt5I3Ojrc2PCxRlBJGyJhujbveSicMA54T01Fk293A,975
22
23
  q3dviewer/shaders/gau_prep.glsl,sha256=0BiWhYCQGeX2iN-e7m3dy1xWXqWrErErRAzHlcmWHF0,7218
23
24
  q3dviewer/shaders/gau_vert.glsl,sha256=_rkm51zaWgPDJ-otJL-WX12fDvnPBOTooVfqo21Rexs,1666
24
25
  q3dviewer/shaders/mesh_frag.glsl,sha256=i9ljnO2kjLNGaR1TPQIK4-4iJ-JppJ5bCsOHg1730gQ,1997
25
- q3dviewer/shaders/mesh_vert.glsl,sha256=tj9pbaWUYoKn1CtYahahPVzXNDTEtaQanq3S3VphmPg,1896
26
+ q3dviewer/shaders/mesh_geom.glsl,sha256=HwNEZy7UAQm-PKEP-LnqHTlsSqZ5eqm49CYZSVylzXk,1964
27
+ q3dviewer/shaders/mesh_vert.glsl,sha256=bFg7HXesdVg7UaGDuZ4g7IpRdSKcfc6jzTcxLjNXkt8,968
26
28
  q3dviewer/shaders/sort_by_key.glsl,sha256=M5RK6uRDp40vVH6XtBIrdJTcYatqXyZwd6kCzEa2DZg,1097
29
+ q3dviewer/shaders/triangle_mesh_geom.glsl,sha256=Uu9WUVbObAUBrtWamQ3trXbmi-Yn9HKWIJPICdjHv_4,1513
30
+ q3dviewer/shaders/triangle_mesh_vert.glsl,sha256=-VTbZ3zZpDI1krMXp7dY0Dz198XqEu7v6lJttO5jQZo,741
27
31
  q3dviewer/tools/__init__.py,sha256=01wG7BGM6VX0QyFBKsqPmyf2e-vrmV_N3-mo-VQ1VBg,20
28
- q3dviewer/tools/cloud_viewer.py,sha256=sZ16uOt5J_3E7H0ZW3NHq0mTkWuoBkRRtwEQgcEv-Io,7794
32
+ q3dviewer/tools/cloud_viewer.py,sha256=94RABpCIn8sATw7I0l7f-Za1j8ulw2io2GICZ7yDRos,8221
29
33
  q3dviewer/tools/example_viewer.py,sha256=C867mLnCBjawS6LGgRsJ_c6-6wztfL9vOBQt85KbbdU,572
30
- q3dviewer/tools/film_maker.py,sha256=xLFgRhFWoMQ37qlvcu1lXWaTWXMNRYlRcZFfHW5JtmQ,16676
34
+ q3dviewer/tools/film_maker.py,sha256=v5En1rm8CS4I7J1mdtvy6AXrkGGOXuDxfvTBuvnLPMs,16640
31
35
  q3dviewer/tools/gaussian_viewer.py,sha256=vIwWmiFhjNmknrEkBLzt2yiegeH7LP3OeNjnGM6GzaI,1633
32
36
  q3dviewer/tools/lidar_calib.py,sha256=hHnsSaQh_Pkdh8tPntt0MgEW26nQyAdC_HQHq4I3sw8,10562
33
37
  q3dviewer/tools/lidar_cam_calib.py,sha256=4CDcZZiFZDeKo2Y2_lXF9tfbiF9dPsz0OjppQdxQsU4,11430
34
38
  q3dviewer/tools/ros_viewer.py,sha256=ARB3I5wohY3maP8dCu0O0hxObd6JFKuK2y7AApVgMWA,2551
35
39
  q3dviewer/utils/__init__.py,sha256=dwTNAAebTiKY4ygv2G1O-w6-TbJnmnNVO2UfJXvJhaQ,107
36
- q3dviewer/utils/cloud_io.py,sha256=vU03lT4Y-4oPPTNV137HBw-tfwwCwpcaoz3ENWfIAN4,12837
40
+ q3dviewer/utils/cloud_io.py,sha256=OLmVQWbrnGrlZHPz3zdoVn79r50JhM6V0zV-KwogEU8,13732
37
41
  q3dviewer/utils/convert_ros_msg.py,sha256=lNbLIawJfwp3VzygdW3dUXkfSG8atg_CoZbQFmt8H70,3142
38
42
  q3dviewer/utils/gl_helper.py,sha256=dRY_kUqyPMr7NTcupUr6_VTvgnj53iE2C0Lk0-oFYsI,1435
39
- q3dviewer/utils/helpers.py,sha256=SqR4YTQZi13FKbkVUYgodXce1JJ_YmrHEIRkUmnIUas,3085
43
+ q3dviewer/utils/helpers.py,sha256=LMKm7R1OvBLoigxqTNN9pS1UlTw0865SFnMY7_IbgX8,3350
40
44
  q3dviewer/utils/maths.py,sha256=zHaPtvVZIuo8xepIXCMeSL9tpx8FahUrq0l4K1oXrBk,8834
41
45
  q3dviewer/utils/range_slider.py,sha256=Cs_xrwt6FCDVxGxan7r-ARd5ySwQ50xnCzcmz0dB_X0,4215
42
- q3dviewer-1.2.2.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
43
- q3dviewer-1.2.2.dist-info/METADATA,sha256=pZQwcgig77nSIonNFabIUAptK75BfyLqrydzgc7FwNg,8049
44
- q3dviewer-1.2.2.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
45
- q3dviewer-1.2.2.dist-info/entry_points.txt,sha256=EOjker7XYaBk70ffvNB_knPcfA33Bnlg21ZjEeM1EyI,362
46
- q3dviewer-1.2.2.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
47
- q3dviewer-1.2.2.dist-info/RECORD,,
46
+ q3dviewer-1.2.4.dist-info/LICENSE,sha256=81cMOyNfw8KLb1JnPYngGHJ5W83gSbZEBU9MEP3tl-E,1124
47
+ q3dviewer-1.2.4.dist-info/METADATA,sha256=C89drDXpYSfUoEd_x005QqHp7Moc-ziC0vuo1XkWSu0,7776
48
+ q3dviewer-1.2.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
49
+ q3dviewer-1.2.4.dist-info/entry_points.txt,sha256=EOjker7XYaBk70ffvNB_knPcfA33Bnlg21ZjEeM1EyI,362
50
+ q3dviewer-1.2.4.dist-info/top_level.txt,sha256=HFFDCbGu28txcGe2HPc46A7EPaguBa_b5oH7bufmxHM,10
51
+ q3dviewer-1.2.4.dist-info/RECORD,,