openscad-cpp-evaluator 0.22.0__tar.gz → 0.23.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 (199) hide show
  1. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/PKG-INFO +1 -1
  2. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/bindings/module.cpp +32 -0
  3. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/export.hpp +9 -0
  4. openscad_cpp_evaluator-0.23.0/include/openscad_cpp_evaluator/mesh_check.hpp +81 -0
  5. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/pyproject.toml +1 -1
  6. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/python/openscad_cpp_evaluator/__init__.py +17 -1
  7. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/CMakeLists.txt +1 -0
  8. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/import.cpp +32 -2
  9. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/export.cpp +16 -0
  10. openscad_cpp_evaluator-0.23.0/src/mesh_check.cpp +418 -0
  11. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/CMakeLists.txt +1 -0
  12. openscad_cpp_evaluator-0.23.0/tests/test_mesh_check.cpp +210 -0
  13. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tools/cli/cli_lib.cpp +7 -0
  14. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/.github/workflows/ci.yml +0 -0
  15. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/.github/workflows/wheels.yml +0 -0
  16. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/.gitignore +0 -0
  17. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/.gitmodules +0 -0
  18. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/CLAUDE.md +0 -0
  19. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/CMakeLists.txt +0 -0
  20. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/LICENSE +0 -0
  21. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/README.md +0 -0
  22. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/bindings/CMakeLists.txt +0 -0
  23. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/bindings/ast_to_py.cpp +0 -0
  24. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/cmake/embed_font.cmake +0 -0
  25. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/examples/CMakeLists.txt +0 -0
  26. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/examples/eval_perf_benchmark.cpp +0 -0
  27. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/examples/manifold_cache_reuse.cpp +0 -0
  28. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/examples/minimal_debugger.cpp +0 -0
  29. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
  30. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/.gitignore +0 -0
  31. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
  32. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
  33. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/README.md +0 -0
  34. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
  35. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
  36. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
  37. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
  38. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
  39. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
  40. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
  41. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
  42. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
  43. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
  44. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
  45. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
  46. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
  47. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
  48. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
  49. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
  50. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
  51. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
  52. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
  53. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
  54. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
  55. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
  56. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
  57. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
  58. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
  59. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
  60. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
  61. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
  62. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
  63. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
  64. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
  65. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
  66. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
  67. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
  68. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
  69. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
  70. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
  71. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
  72. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
  73. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
  74. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
  75. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
  76. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
  77. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
  78. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
  79. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
  80. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
  81. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
  82. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
  83. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
  84. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
  85. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
  86. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
  87. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
  88. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
  89. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
  90. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
  91. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
  92. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
  93. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
  94. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
  95. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
  96. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
  97. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
  98. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
  99. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
  100. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
  101. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
  102. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
  103. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
  104. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
  105. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
  106. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
  107. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
  108. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
  109. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
  110. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
  111. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
  112. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
  113. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
  114. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
  115. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
  116. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
  117. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
  118. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
  119. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
  120. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/stb_font_provider.hpp +0 -0
  121. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
  122. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
  123. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
  124. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
  125. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/resources/fonts/LICENSE +0 -0
  126. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
  127. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/booleans.cpp +0 -0
  128. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/builtins.hpp +0 -0
  129. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/call_args.cpp +0 -0
  130. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/color.cpp +0 -0
  131. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/control.cpp +0 -0
  132. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/extrude.cpp +0 -0
  133. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/function_builtins.cpp +0 -0
  134. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/modifiers.cpp +0 -0
  135. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/primitives_2d.cpp +0 -0
  136. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/primitives_3d.cpp +0 -0
  137. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/registry.cpp +0 -0
  138. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/roof.cpp +0 -0
  139. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/segments.cpp +0 -0
  140. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/surface.cpp +0 -0
  141. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/text.cpp +0 -0
  142. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/topology.cpp +0 -0
  143. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/builtins/transforms.cpp +0 -0
  144. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/bytecode_compiler.cpp +0 -0
  145. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/bytecode_vm.cpp +0 -0
  146. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/colored_body.cpp +0 -0
  147. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/csg_generate.cpp +0 -0
  148. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/csg_resolve.cpp +0 -0
  149. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/css_colors.cpp +0 -0
  150. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/debug/debug_repl.cpp +0 -0
  151. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/debug_profile.cpp +0 -0
  152. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/eval_context.cpp +0 -0
  153. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/eval_error.cpp +0 -0
  154. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/eval_use.cpp +0 -0
  155. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/expr_eval.cpp +0 -0
  156. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/import/dxf_import.cpp +0 -0
  157. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/import/mesh_import.cpp +0 -0
  158. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/import/surface_load.cpp +0 -0
  159. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/import/svg_import.cpp +0 -0
  160. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/manifold_cache.cpp +0 -0
  161. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/stmt_eval.cpp +0 -0
  162. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/text/stb_font_provider.cpp +0 -0
  163. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/text/text_metrics.cpp +0 -0
  164. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/user_calls.cpp +0 -0
  165. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/value.cpp +0 -0
  166. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/src/zip_stored.cpp +0 -0
  167. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_booleans.cpp +0 -0
  168. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_bytecode_compiler.cpp +0 -0
  169. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_cli.cpp +0 -0
  170. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_control_flow.cpp +0 -0
  171. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_csg_tree.cpp +0 -0
  172. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_debug_hooks.cpp +0 -0
  173. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_dxf_svg_import.cpp +0 -0
  174. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_eval_context.cpp +0 -0
  175. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_export.cpp +0 -0
  176. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_expr_eval.cpp +0 -0
  177. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_extrude_roof.cpp +0 -0
  178. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_function_builtins.cpp +0 -0
  179. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_helpers.hpp +0 -0
  180. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_import_export.cpp +0 -0
  181. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_manifold_cache.cpp +0 -0
  182. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_multi_color_merge.cpp +0 -0
  183. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_primitives.cpp +0 -0
  184. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_profiling.cpp +0 -0
  185. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_python_bindings.py +0 -0
  186. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_scope_trail.cpp +0 -0
  187. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_scoping.cpp +0 -0
  188. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_surface.cpp +0 -0
  189. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_tail_calls.cpp +0 -0
  190. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_text.cpp +0 -0
  191. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_transforms.cpp +0 -0
  192. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_use.cpp +0 -0
  193. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_value.cpp +0 -0
  194. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_viewport_params.cpp +0 -0
  195. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tests/test_zip_stored.cpp +0 -0
  196. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tools/cli/CMakeLists.txt +0 -0
  197. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tools/cli/cli_lib.hpp +0 -0
  198. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/tools/cli/main.cpp +0 -0
  199. {openscad_cpp_evaluator-0.22.0 → openscad_cpp_evaluator-0.23.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openscad_cpp_evaluator
3
- Version: 0.22.0
3
+ Version: 0.23.0
4
4
  Summary: C++ OpenSCAD evaluator with Python bindings
5
5
  Author: NeuSCAD Contributors
6
6
  License-Expression: MIT
@@ -14,6 +14,7 @@
14
14
  #include <nanobind/nanobind.h>
15
15
  #include <nanobind/ndarray.h>
16
16
  #include <nanobind/stl/shared_ptr.h>
17
+ #include <nanobind/stl/vector.h>
17
18
  #include <nanobind/stl/string.h>
18
19
 
19
20
  #include "openscad_cpp_evaluator/colored_body.hpp"
@@ -21,6 +22,7 @@
21
22
  #include "openscad_cpp_evaluator/eval_context.hpp"
22
23
  #include "openscad_cpp_evaluator/eval_use.hpp"
23
24
  #include "openscad_cpp_evaluator/evaluator.hpp"
25
+ #include "openscad_cpp_evaluator/mesh_check.hpp"
24
26
  #include "openscad_cpp_evaluator/manifold_cache.hpp"
25
27
  #include "openscad_cpp_evaluator/profile.hpp"
26
28
  #include "openscad_cpp_evaluator/value.hpp"
@@ -242,6 +244,31 @@ nb::list csgTreeToPy(const std::vector<std::unique_ptr<oscadeval::CSGNode>>& tre
242
244
  return out;
243
245
  }
244
246
 
247
+ // Exposed so a front end that writes its own files -- BelfrySCAD's GUI has
248
+ // its own exporters -- can run the same check the CLI does rather than a
249
+ // second, drifting implementation.
250
+ nb::dict checkMeshPy(const std::vector<float>& verts, const std::vector<uint32_t>& tris) {
251
+ manifold::MeshGL m;
252
+ m.numProp = 3;
253
+ m.vertProperties = verts;
254
+ m.triVerts = tris;
255
+ const oscadeval::MeshDiagnosis d = oscadeval::checkMesh(m);
256
+ nb::dict out;
257
+ out["boundary_edges"] = d.boundaryEdges;
258
+ out["non_manifold_edges"] = d.nonManifoldEdges;
259
+ out["pinched_vertices"] = d.pinchedVertices;
260
+ out["inconsistent_edges"] = d.inconsistentEdges;
261
+ out["degenerate_faces"] = d.degenerateFaces;
262
+ out["duplicate_faces"] = d.duplicateFaces;
263
+ out["unwelded_vertices"] = d.unweldedVertices;
264
+ out["watertight"] = d.watertight();
265
+ out["manifold"] = d.manifold();
266
+ out["orientable"] = d.orientable();
267
+ out["ok"] = d.ok();
268
+ out["summary"] = d.summary();
269
+ return out;
270
+ }
271
+
245
272
  nb::object profileResultToPy(const std::optional<oscadeval::ProfileResult>& pr) {
246
273
  if (!pr) return nb::none();
247
274
  nb::list sites;
@@ -681,6 +708,11 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
681
708
  "Evaluate a .scad file; return (bodies, echoes, id_to_node, csg_tree, profile_result, dyn, dyn_explicit).");
682
709
  m.def("parse_decls", &parseDecls, nb::arg("path"),
683
710
  "Parse a .scad file; return top-level declaration (namespace, name, start, end, line, column, origin) tuples.");
711
+ m.def("check_mesh", &checkMeshPy, nb::arg("verts"), nb::arg("tris"),
712
+ "Diagnose a triangle mesh against the manifoldness conditions. "
713
+ "verts is a flat [x,y,z,...] list, tris a flat index list. Returns "
714
+ "counts per condition plus watertight/manifold/orientable/ok and a "
715
+ "one-line summary.");
684
716
  m.def("parse_ast", &oscadbind::parseAstFromFile, nb::arg("path"), nb::arg("include_comments") = false,
685
717
  "Parse a .scad file; return the AST as a list of plain nested dicts "
686
718
  "(kind, position, plus that kind's own fields). A snapshot, not a view -- "
@@ -17,6 +17,15 @@ namespace oscadeval {
17
17
  //
18
18
  // 3MF and format-from-extension dispatch land in Phase 5 per the plan's
19
19
  // phased build order.
20
+ // One message per body that is not a closed manifold solid, ready to print.
21
+ // Empty when everything is sound.
22
+ //
23
+ // Returned rather than logged so each front end can surface it its own way,
24
+ // and so export.cpp needs no logging dependency. Nothing here refuses to
25
+ // write: a deliberately open surface is a legitimate thing to export, and
26
+ // silently blocking a save would be worse than an honest warning.
27
+ std::vector<std::string> checkExportBodies(const std::vector<ColoredBody>& bodies);
28
+
20
29
  void writeStl(const std::string& path, const std::vector<ColoredBody>& bodies);
21
30
 
22
31
  // Wavefront OBJ: "v x y z" per vertex then "f i j k" per triangle
@@ -0,0 +1,81 @@
1
+ #pragma once
2
+
3
+ #include <cstdint>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+ #include <manifold/manifold.h>
8
+
9
+ namespace oscadeval {
10
+
11
+ // What is wrong with a triangle mesh, as four independent conditions. They
12
+ // are separate because they fail separately and a mesh can satisfy any
13
+ // subset: two boxes fused along a face are watertight but have edges with
14
+ // four faces; two cones joined tip-to-tip have every edge shared by exactly
15
+ // two faces and still pinch at the apex.
16
+ struct MeshDiagnosis {
17
+ // Edges used by exactly one face: a hole.
18
+ size_t boundaryEdges = 0;
19
+ // Edges used by three or more faces: surfaces meeting along a seam.
20
+ size_t nonManifoldEdges = 0;
21
+ // Vertices whose incident faces form more than one fan -- the surface
22
+ // pinches to a point there. Passes the edge test, so it needs its own.
23
+ size_t pinchedVertices = 0;
24
+ // Edges whose two faces traverse them the same way round rather than in
25
+ // opposite directions: the winding disagrees across that edge.
26
+ size_t inconsistentEdges = 0;
27
+ // Zero-area triangles, and faces naming the same vertex twice.
28
+ size_t degenerateFaces = 0;
29
+ // Faces with the same three vertices as another face.
30
+ size_t duplicateFaces = 0;
31
+ // Distinct indices at the same position. These split what should be one
32
+ // edge into two boundary edges, which is the usual reason a mesh that
33
+ // looks closed is not.
34
+ size_t unweldedVertices = 0;
35
+
36
+ bool watertight() const { return boundaryEdges == 0; }
37
+ bool manifold() const {
38
+ return boundaryEdges == 0 && nonManifoldEdges == 0 && pinchedVertices == 0
39
+ && degenerateFaces == 0;
40
+ }
41
+ bool orientable() const { return inconsistentEdges == 0; }
42
+ bool ok() const { return manifold() && orientable(); }
43
+
44
+ // "4 boundary edges, 1 pinched vertex" -- empty when nothing is wrong.
45
+ std::string summary() const;
46
+ };
47
+
48
+ // Diagnose `mesh` against all four conditions. Read-only; nothing is
49
+ // modified and no exception is thrown for a broken mesh.
50
+ MeshDiagnosis checkMesh(const manifold::MeshGL& mesh);
51
+
52
+ // What repairMesh did, for reporting. Not a diagnosis: these are actions.
53
+ struct MeshRepairReport {
54
+ size_t weldedVertices = 0;
55
+ size_t droppedDegenerate = 0;
56
+ size_t droppedDuplicate = 0;
57
+ size_t reversedFaces = 0;
58
+ size_t filledHoles = 0;
59
+ size_t filledTriangles = 0;
60
+ size_t splitVertices = 0;
61
+ size_t unfilledHoles = 0; // boundary loops it could not close
62
+
63
+ bool didAnything() const {
64
+ return weldedVertices || droppedDegenerate || droppedDuplicate || reversedFaces
65
+ || filledHoles || splitVertices;
66
+ }
67
+ // "welded 12 vertices, filled 1 hole (4 triangles)" -- empty if nothing.
68
+ std::string summary() const;
69
+ };
70
+
71
+ // Best-effort repair, in the only order that works: welding first (it
72
+ // changes which edges are shared, so every later test depends on it), then
73
+ // degenerate and duplicate removal, then orientation, then hole filling
74
+ // last -- filling before orienting would add faces wound against their
75
+ // neighbours.
76
+ //
77
+ // Returns the repaired mesh. A mesh it cannot close is still returned,
78
+ // improved as far as it got, with the remainder reported in `report`.
79
+ manifold::MeshGL repairMesh(const manifold::MeshGL& mesh, MeshRepairReport& report);
80
+
81
+ } // namespace oscadeval
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "openscad_cpp_evaluator"
7
- version = "0.22.0"
7
+ version = "0.23.0"
8
8
  description = "C++ OpenSCAD evaluator with Python bindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -18,7 +18,7 @@ from ._openscad_cpp_evaluator import FastContinueSignal, ManifoldCache
18
18
  __all__ = [
19
19
  "Evaluator", "ColoredBody", "EvalError", "ParseError", "OscObject", "parse", "to_renderable_bodies",
20
20
  "ManifoldCache", "CallSiteProfile", "ProfileResult", "format_csg_tree", "bodies_from_dicts",
21
- "FastContinueSignal", "parse_ast", "parse_ast_string",
21
+ "FastContinueSignal", "parse_ast", "parse_ast_string", "check_mesh",
22
22
  ]
23
23
 
24
24
 
@@ -274,6 +274,22 @@ def parse(path: str) -> RootScope:
274
274
  return RootScope(decls)
275
275
 
276
276
 
277
+ def check_mesh(verts, tris) -> dict:
278
+ """Diagnose a triangle mesh against the manifoldness conditions.
279
+
280
+ `verts` is a flat [x, y, z, ...] sequence, `tris` a flat index sequence.
281
+ Returns a count per condition -- boundary_edges, non_manifold_edges,
282
+ pinched_vertices, inconsistent_edges, degenerate_faces, duplicate_faces,
283
+ unwelded_vertices -- plus watertight/manifold/orientable/ok and a
284
+ one-line `summary`.
285
+
286
+ The conditions are separate because they fail separately: a mesh can be
287
+ watertight and still non-manifold, and one that is both can still be
288
+ wound inconsistently.
289
+ """
290
+ return _ext.check_mesh([float(v) for v in verts], [int(t) for t in tris])
291
+
292
+
277
293
  def parse_ast(path: str, include_comments: bool = False) -> list:
278
294
  """Parse a .scad file; return its AST as a list of plain nested dicts.
279
295
 
@@ -15,6 +15,7 @@ add_library(openscad_cpp_evaluator STATIC
15
15
  debug_profile.cpp
16
16
  eval_use.cpp
17
17
  export.cpp
18
+ mesh_check.cpp
18
19
  zip_stored.cpp
19
20
  import/mesh_import.cpp
20
21
  import/surface_load.cpp
@@ -7,6 +7,8 @@
7
7
  #include "openscad_cpp_evaluator/mesh_import.hpp"
8
8
 
9
9
  #include <manifold/manifold.h>
10
+
11
+ #include "openscad_cpp_evaluator/mesh_check.hpp"
10
12
  #include <nlohmann/json.hpp>
11
13
 
12
14
  #include <algorithm>
@@ -174,6 +176,9 @@ CSGParams resolveImport(Evaluator& ev, const oscad::ModularCall& node, EvalConte
174
176
  auto [args, effCtx] = resolveCallArgs(ev, node.arguments, ctx);
175
177
  const Value fileArg = getArg(args, 0, "file", Value{});
176
178
  const Value layerArg = getArg(args, std::nullopt, "layer", Value{});
179
+ // Not an OpenSCAD parameter. A script using it will not run upstream,
180
+ // which is why it has to be asked for rather than being the default.
181
+ const bool repair = truthy(getArg(args, std::nullopt, "repair", Value{false}));
177
182
 
178
183
  CSGParams params;
179
184
  params["color"] = colorToValue(effCtx.color);
@@ -225,6 +230,7 @@ CSGParams resolveImport(Evaluator& ev, const oscad::ModularCall& node, EvalConte
225
230
  trisFlat.push_back(Value{static_cast<double>(t[2])});
226
231
  }
227
232
  params["kind"] = Value{std::string("mesh")};
233
+ params["repair"] = Value{repair};
228
234
  params["verts"] = Value{std::make_shared<const ValueList>(ValueList{std::move(vertsFlat)})};
229
235
  params["tris"] = Value{std::make_shared<const ValueList>(ValueList{std::move(trisFlat)})};
230
236
  return params;
@@ -268,6 +274,26 @@ std::vector<ColoredBody> generateImport(Evaluator& ev, const CSGParams& params,
268
274
  }
269
275
  for (const Value& t : tris) mesh.triVerts.push_back(static_cast<uint32_t>(std::get<double>(t)));
270
276
 
277
+ const auto repairIt = params.find("repair");
278
+ const bool repair = repairIt != params.end() && truthy(repairIt->second);
279
+ if (repair) {
280
+ const MeshDiagnosis before = checkMesh(mesh);
281
+ MeshRepairReport rep;
282
+ manifold::MeshGL fixed = repairMesh(mesh, rep);
283
+ const MeshDiagnosis after = checkMesh(fixed);
284
+ if (rep.didAnything()) {
285
+ ev.warn("import: repaired the mesh -- " + rep.summary(), &node.position());
286
+ }
287
+ if (!after.ok() && !before.ok()) {
288
+ // Say what is left rather than only what was done: a repair
289
+ // that helped but did not finish is the case where the user
290
+ // most needs to know the difference.
291
+ ev.warn("import: still not manifold after repair -- " + after.summary(),
292
+ &node.position());
293
+ }
294
+ mesh = std::move(fixed);
295
+ }
296
+
271
297
  manifold::Manifold body(mesh);
272
298
  if (body.Status() != manifold::Manifold::Error::NoError) {
273
299
  // Same treatment as an open polyhedron() (see generatePolyhedron):
@@ -275,8 +301,12 @@ std::vector<ColoredBody> generateImport(Evaluator& ev, const CSGParams& params,
275
301
  // this warned and then handed back an empty body, which was dropped
276
302
  // downstream -- so a broken STL warned once and showed nothing,
277
303
  // giving no way to see what was actually wrong with it.
278
- ev.warn("import: mesh is not a closed solid (" + manifoldErrorName(body.Status()) +
279
- "); drawing it as a surface, but it cannot take part in any CSG operation",
304
+ const MeshDiagnosis d = checkMesh(mesh);
305
+ std::string why = d.summary();
306
+ if (why.empty()) why = manifoldErrorName(body.Status());
307
+ ev.warn("import: mesh is not a closed solid (" + why +
308
+ "); drawing it as a surface, but it cannot take part in any CSG "
309
+ "operation" + (repair ? "" : ". Try import(..., repair=true)"),
280
310
  &node.position());
281
311
  return {ev.tagDisplayOnly(std::move(mesh), node, params.at("color"))};
282
312
  }
@@ -1,5 +1,7 @@
1
1
  #include "openscad_cpp_evaluator/export.hpp"
2
2
 
3
+ #include "openscad_cpp_evaluator/mesh_check.hpp"
4
+
3
5
  #include "openscad_cpp_evaluator/zip_stored.hpp"
4
6
 
5
7
  #include <manifold/manifold.h>
@@ -223,4 +225,18 @@ void writeThreeMf(const std::string& path, const std::vector<ColoredBody>& bodie
223
225
  writeDeflateZip(path, entries);
224
226
  }
225
227
 
228
+ std::vector<std::string> checkExportBodies(const std::vector<ColoredBody>& bodies) {
229
+ std::vector<std::string> out;
230
+ size_t n = 0;
231
+ for (const auto& b : bodies) {
232
+ ++n;
233
+ if (!b.body || b.body->IsEmpty()) continue;
234
+ const MeshDiagnosis d = checkMesh(b.body->GetMeshGL());
235
+ if (d.ok()) continue;
236
+ out.push_back("part " + std::to_string(n) + " is not a closed manifold solid -- "
237
+ + d.summary());
238
+ }
239
+ return out;
240
+ }
241
+
226
242
  } // namespace oscadeval