session-py 0.166.0__tar.gz → 0.167.0__tar.gz

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 (133) hide show
  1. {session_py-0.166.0 → session_py-0.167.0}/PKG-INFO +1 -1
  2. {session_py-0.166.0 → session_py-0.167.0}/pyproject.toml +1 -1
  3. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/session.py +44 -12
  4. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/session_test.py +36 -0
  5. {session_py-0.166.0 → session_py-0.167.0}/.github/workflows/publish.yml +0 -0
  6. {session_py-0.166.0 → session_py-0.167.0}/.github/workflows/test.yml +0 -0
  7. {session_py-0.166.0 → session_py-0.167.0}/.gitignore +0 -0
  8. {session_py-0.166.0 → session_py-0.167.0}/.gitmodules +0 -0
  9. {session_py-0.166.0 → session_py-0.167.0}/AGENTS.md +0 -0
  10. {session_py-0.166.0 → session_py-0.167.0}/README.md +0 -0
  11. {session_py-0.166.0 → session_py-0.167.0}/conftest.py +0 -0
  12. {session_py-0.166.0 → session_py-0.167.0}/examples/bvh_demo.py +0 -0
  13. {session_py-0.166.0 → session_py-0.167.0}/examples/loft_holes.py +0 -0
  14. {session_py-0.166.0 → session_py-0.167.0}/examples/nurbsurface.py +0 -0
  15. {session_py-0.166.0 → session_py-0.167.0}/serialization/.gitkeep +0 -0
  16. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/__init__.py +0 -0
  17. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/aabb.py +0 -0
  18. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/aabb_test.py +0 -0
  19. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/boolean_polyline.py +0 -0
  20. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/boolean_polyline_test.py +0 -0
  21. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/brep.py +0 -0
  22. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/brep_test.py +0 -0
  23. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/closest.py +0 -0
  24. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/closest_test.py +0 -0
  25. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/color.py +0 -0
  26. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/color_test.py +0 -0
  27. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/convex_hull.py +0 -0
  28. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/convex_hull_test.py +0 -0
  29. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/element.py +0 -0
  30. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/element_test.py +0 -0
  31. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/file_encoders.py +0 -0
  32. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/file_encoders_test.py +0 -0
  33. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/file_obj.py +0 -0
  34. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/file_obj_test.py +0 -0
  35. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/graph.py +0 -0
  36. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/graph_test.py +0 -0
  37. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/instance_ref.py +0 -0
  38. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/instance_ref_test.py +0 -0
  39. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/intersection.py +0 -0
  40. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/intersection_test.py +0 -0
  41. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/io.py +0 -0
  42. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/io_test.py +0 -0
  43. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/line.py +0 -0
  44. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/line_test.py +0 -0
  45. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/matrix.py +0 -0
  46. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/matrix_test.py +0 -0
  47. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/mesh.py +0 -0
  48. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/mesh_offset.py +0 -0
  49. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/mesh_offset_test.py +0 -0
  50. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/mesh_test.py +0 -0
  51. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/mini_test.py +0 -0
  52. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbscurve.py +0 -0
  53. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbscurve_test.py +0 -0
  54. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbsknot.py +0 -0
  55. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbsknot_test.py +0 -0
  56. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbssurface.py +0 -0
  57. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbssurface_test.py +0 -0
  58. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbssurface_trimmed.py +0 -0
  59. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/nurbssurface_trimmed_test.py +0 -0
  60. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/obb.py +0 -0
  61. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/obb_test.py +0 -0
  62. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/objects.py +0 -0
  63. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/objects_test.py +0 -0
  64. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/plane.py +0 -0
  65. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/plane_test.py +0 -0
  66. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/point.py +0 -0
  67. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/point_test.py +0 -0
  68. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/pointcloud.py +0 -0
  69. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/pointcloud_test.py +0 -0
  70. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/polyline.py +0 -0
  71. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/polyline_test.py +0 -0
  72. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/primitives.py +0 -0
  73. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/primitives_test.py +0 -0
  74. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/.gitattributes +0 -0
  75. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/__init__.py +0 -0
  76. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/boundingbox_pb2.py +0 -0
  77. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/brep_pb2.py +0 -0
  78. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/color_pb2.py +0 -0
  79. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/edge_pb2.py +0 -0
  80. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/element_pb2.py +0 -0
  81. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/file_encoders_pb2.py +0 -0
  82. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/graph_pb2.py +0 -0
  83. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/instance_ref_pb2.py +0 -0
  84. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/line_pb2.py +0 -0
  85. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/matrix_pb2.py +0 -0
  86. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/mesh_pb2.py +0 -0
  87. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/nurbscurve_pb2.py +0 -0
  88. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/nurbssurface_pb2.py +0 -0
  89. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/nurbssurface_trimmed_pb2.py +0 -0
  90. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/objects_pb2.py +0 -0
  91. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/plane_pb2.py +0 -0
  92. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/point_pb2.py +0 -0
  93. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/pointcloud_pb2.py +0 -0
  94. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/polyline_pb2.py +0 -0
  95. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/quaternion_pb2.py +0 -0
  96. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/session_pb2.py +0 -0
  97. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/tolerance_pb2.py +0 -0
  98. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/tree_pb2.py +0 -0
  99. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/treenode_pb2.py +0 -0
  100. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/vector_pb2.py +0 -0
  101. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/vertex_pb2.py +0 -0
  102. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/proto/xform_pb2.py +0 -0
  103. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/py.typed +0 -0
  104. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/quaternion.py +0 -0
  105. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/quaternion_test.py +0 -0
  106. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/reload.py +0 -0
  107. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_cdt.py +0 -0
  108. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_cdt_test.py +0 -0
  109. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_nurbssurface_adaptive.py +0 -0
  110. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_nurbssurface_adaptive_test.py +0 -0
  111. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_nurbssurface_grid.py +0 -0
  112. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/remesh_nurbssurface_grid_test.py +0 -0
  113. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/session_config.py +0 -0
  114. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/session_config_test.py +0 -0
  115. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_aabbtree.py +0 -0
  116. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_aabbtree_test.py +0 -0
  117. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_bvh.py +0 -0
  118. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_bvh_test.py +0 -0
  119. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_kdtree.py +0 -0
  120. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_kdtree_test.py +0 -0
  121. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_octree.py +0 -0
  122. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_octree_test.py +0 -0
  123. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_rtree.py +0 -0
  124. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/spatial_rtree_test.py +0 -0
  125. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/tolerance.py +0 -0
  126. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/tolerance_test.py +0 -0
  127. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/tree.py +0 -0
  128. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/tree_test.py +0 -0
  129. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/vector.py +0 -0
  130. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/vector_test.py +0 -0
  131. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/xform.py +0 -0
  132. {session_py-0.166.0 → session_py-0.167.0}/src/session_py/xform_test.py +0 -0
  133. {session_py-0.166.0 → session_py-0.167.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: session_py
3
- Version: 0.166.0
3
+ Version: 0.167.0
4
4
  Summary: A minimal Python geometry library
5
5
  Project-URL: Homepage, https://github.com/petrasvestartas/session_py
6
6
  Project-URL: Repository, https://github.com/petrasvestartas/session_py
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "session_py"
7
- version = "0.166.0"
7
+ version = "0.167.0"
8
8
  description = "A minimal Python geometry library"
9
9
  authors = [{name = "Petras Vestartas", email = "petrasvestartas@gmail.com"}]
10
10
  license = {text = "MIT"}
@@ -343,6 +343,11 @@ class Session:
343
343
 
344
344
  # ═══════════════════════════════════════════════════════════════════════════
345
345
  # Details - Add objects
346
+ #
347
+ # Every add_* below SKIPS an object that is None or carries nothing to draw, and returns
348
+ # None instead of a node: an empty point cloud, a polyline of fewer than two points, a
349
+ # mesh without faces. The check lives here so no caller has to write it, and so a scene
350
+ # never holds an object a viewer cannot render.
346
351
  # ═══════════════════════════════════════════════════════════════════════════
347
352
 
348
353
  def _add_object(self, collection, obj, type_prefix, parent=None):
@@ -372,37 +377,61 @@ class Session:
372
377
  + [e.guid for e in self.objects.elements]
373
378
  )
374
379
 
375
- def add_point(self, point: Point, parent: TreeNode | None = None) -> TreeNode:
380
+ def add_point(self, point: Point, parent: TreeNode | None = None) -> TreeNode | None:
381
+ if point is None:
382
+ return None
376
383
  return self._add_object(self.objects.points, point, "point", parent)
377
384
 
378
- def add_line(self, line: "Line", parent: TreeNode | None = None) -> TreeNode:
385
+ def add_line(self, line: "Line", parent: TreeNode | None = None) -> TreeNode | None:
386
+ if line is None:
387
+ return None
379
388
  return self._add_object(self.objects.lines, line, "line", parent)
380
389
 
381
- def add_plane(self, plane: "Plane", parent: TreeNode | None = None) -> TreeNode:
390
+ def add_plane(self, plane: "Plane", parent: TreeNode | None = None) -> TreeNode | None:
391
+ if plane is None:
392
+ return None
382
393
  return self._add_object(self.objects.planes, plane, "plane", parent)
383
394
 
384
- def add_obb(self, bbox: "OBB", parent: TreeNode | None = None) -> TreeNode:
395
+ def add_obb(self, bbox: "OBB", parent: TreeNode | None = None) -> TreeNode | None:
396
+ if bbox is None:
397
+ return None
385
398
  return self._add_object(self.objects.bboxes, bbox, "bbox", parent)
386
399
 
387
- def add_polyline(self, polyline: "Polyline", parent: TreeNode | None = None) -> TreeNode:
400
+ def add_polyline(self, polyline: "Polyline", parent: TreeNode | None = None) -> TreeNode | None:
401
+ if polyline is None or polyline.point_count() < 2:
402
+ return None
388
403
  return self._add_object(self.objects.polylines, polyline, "polyline", parent)
389
404
 
390
- def add_pointcloud(self, pointcloud: "PointCloud", parent: TreeNode | None = None) -> TreeNode:
405
+ def add_pointcloud(self, pointcloud: "PointCloud", parent: TreeNode | None = None) -> TreeNode | None:
406
+ if pointcloud is None or pointcloud.is_empty():
407
+ return None
391
408
  return self._add_object(self.objects.pointclouds, pointcloud, "pointcloud", parent)
392
409
 
393
- def add_mesh(self, mesh: "Mesh", parent: TreeNode | None = None) -> TreeNode:
410
+ def add_mesh(self, mesh: "Mesh", parent: TreeNode | None = None) -> TreeNode | None:
411
+ if mesh is None or mesh.is_empty() or mesh.number_of_faces() == 0:
412
+ return None
394
413
  return self._add_object(self.objects.meshes, mesh, "mesh", parent)
395
414
 
396
- def add_nurbscurve(self, nurbscurve: "NurbsCurve", parent: TreeNode | None = None) -> TreeNode:
415
+ def add_nurbscurve(self, nurbscurve: "NurbsCurve", parent: TreeNode | None = None) -> TreeNode | None:
416
+ if nurbscurve is None or nurbscurve.cv_count() < 2:
417
+ return None
397
418
  return self._add_object(self.objects.nurbscurves, nurbscurve, "nurbscurve", parent)
398
419
 
399
- def add_nurbssurface(self, nurbssurface: "NurbsSurface", parent: TreeNode | None = None) -> TreeNode:
420
+ def add_nurbssurface(self, nurbssurface: "NurbsSurface", parent: TreeNode | None = None) -> TreeNode | None:
421
+ if nurbssurface is None or nurbssurface.cv_count() == 0:
422
+ return None
400
423
  return self._add_object(self.objects.nurbssurfaces, nurbssurface, "nurbssurface", parent)
401
424
 
402
- def add_brep(self, brep: "BRep", parent: TreeNode | None = None) -> TreeNode:
425
+ def add_brep(self, brep: "BRep", parent: TreeNode | None = None) -> TreeNode | None:
426
+ if brep is None or (brep.face_count() == 0 and brep.vertex_count() == 0):
427
+ return None
403
428
  return self._add_object(self.objects.breps, brep, "brep", parent)
404
429
 
405
- def add_element(self, element: "Element", parent: TreeNode | None = None) -> TreeNode:
430
+ def add_element(self, element: "Element", parent: TreeNode | None = None) -> TreeNode | None:
431
+ # Kept even with no geometry: an Element is a data record - features, insertion vectors,
432
+ # element_data a consumer reads back - and dropping one would lose that on a round trip.
433
+ if element is None:
434
+ return None
406
435
  return self._add_object(self.objects.elements, element, "element", parent)
407
436
 
408
437
  def add_component(self, component: Any, parent: TreeNode | None = None) -> TreeNode:
@@ -432,10 +461,13 @@ class Session:
432
461
  Parameters
433
462
  ----------
434
463
  node : TreeNode
435
- The TreeNode to add.
464
+ The TreeNode to add. None is ignored, so passing an add_* result straight
465
+ through works even when that add_* skipped its geometry.
436
466
  parent : TreeNode, optional
437
467
  Parent TreeNode (defaults to root if not provided).
438
468
  """
469
+ if node is None:
470
+ return
439
471
  if parent is None:
440
472
  self.tree.add(node, self.tree.root)
441
473
  else:
@@ -215,6 +215,42 @@ def test_session_add_element():
215
215
  MINI_CHECK(session.graph.has_node(plate.guid))
216
216
 
217
217
 
218
+ @MINI_TEST("Session", "Add Empty Geometry")
219
+ def test_session_add_empty_geometry():
220
+ from session_py import Session
221
+ from session_py import Point
222
+ from session_py import Polyline
223
+ from session_py import PointCloud
224
+ from session_py import Mesh
225
+ from session_py import NurbsCurve
226
+ from session_py import NurbsSurface
227
+ from session_py import BRep
228
+
229
+ # Nothing to draw is never added: the caller does not test its geometry first.
230
+ session = Session()
231
+ group = session.add_group("empty")
232
+
233
+ MINI_CHECK(session.add_point(None, group) is None)
234
+ MINI_CHECK(session.add_polyline(Polyline([Point(0, 0, 0)]), group) is None)
235
+ MINI_CHECK(session.add_pointcloud(PointCloud([], [], []), group) is None)
236
+ MINI_CHECK(session.add_mesh(Mesh(), group) is None)
237
+ MINI_CHECK(session.add_nurbscurve(NurbsCurve(), group) is None)
238
+ MINI_CHECK(session.add_nurbssurface(NurbsSurface(), group) is None)
239
+ MINI_CHECK(session.add_brep(BRep(), group) is None)
240
+
241
+ # A mesh with vertices but no faces draws nothing either.
242
+ vertices_only = Mesh()
243
+ vertices_only.add_vertex(Point(0, 0, 0), 0)
244
+ MINI_CHECK(session.add_mesh(vertices_only, group) is None)
245
+
246
+ # add(add_XXX(...), group) stays a valid one-liner when the geometry was skipped.
247
+ session.add(session.add_mesh(Mesh(), group), group)
248
+
249
+ MINI_CHECK(len(session.lookup) == 0)
250
+ MINI_CHECK(len(session.order()) == 0)
251
+ MINI_CHECK(len(group.children) == 0)
252
+
253
+
218
254
  @MINI_TEST("Session", "Add Group")
219
255
  def test_session_add_group():
220
256
  from session_py import Session
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes