openscad-cpp-evaluator 1.32.0__tar.gz → 1.33.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.
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/CLAUDE.md +16 -2
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/bindings/module.cpp +22 -3
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/export.hpp +30 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/python/openscad_cpp_evaluator/__init__.py +8 -2
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/export.cpp +158 -2
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_export.cpp +118 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_python_bindings.py +34 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tools/cli/main.cpp +0 -0
|
@@ -1091,8 +1091,8 @@ grep for `ponytail:`.
|
|
|
1091
1091
|
— skip it and the mesh comes out non-manifold at the seam). Self-contained 2D geometry math here
|
|
1092
1092
|
(`dot2`/`len2`/`norm2`, the parabola-canonical-frame rotation in `discretizeArc`) exists nowhere
|
|
1093
1093
|
else in this codebase.
|
|
1094
|
-
- `include/openscad_cpp_evaluator/export.hpp`, `src/export.cpp` — the writers for all
|
|
1095
|
-
formats `exportExtensions()` lists: 3MF, AMF, DXF, PDF, STL, OBJ, OFF, PLY, SVG, VRML, X3D (3MF via
|
|
1094
|
+
- `include/openscad_cpp_evaluator/export.hpp`, `src/export.cpp` — the writers for all twelve
|
|
1095
|
+
formats `exportExtensions()` lists: 3MF, AMF, DXF, PDF, STL, OBJ, OFF, PLY, POV, SVG, VRML, X3D (3MF via
|
|
1096
1096
|
`zip_stored.hpp`'s `writeDeflateZip`). **`exportExtensions()` is the one source of truth for
|
|
1097
1097
|
which formats exist** — the Python facade and BelfrySCAD's dialog/CLI all ask it rather than
|
|
1098
1098
|
restating the list, because three hand-written copies had already drifted far enough that `.off`
|
|
@@ -1120,6 +1120,20 @@ grep for `ponytail:`.
|
|
|
1120
1120
|
binary's, vertex order and 6-vertex line wrap included. A 3D body in the list throws
|
|
1121
1121
|
("Current top level object is not a 2D object"), as OpenSCAD refuses too: there is no projection
|
|
1122
1122
|
to fall back on. `ExportOptions::svg` carries OpenSCAD's five `-O export-svg/...` settings.
|
|
1123
|
+
**`writePov` writes POV-Ray, as `mesh2`** — one per object `splitBodiesForExport` produces, with
|
|
1124
|
+
a welded vertex list, a `texture_list` of the object's colours and a texture index per triangle
|
|
1125
|
+
(so per-triangle colour needs no unwelding, unlike PLY), and `inside_vector` so POV-Ray treats it
|
|
1126
|
+
as a SOLID (the `ior 1.32` interior refracts; CSG works). OpenSCAD's `export_pov.cc` writes every
|
|
1127
|
+
face as its own flat `polygon` object instead. The rest of the scene is OpenSCAD's: header,
|
|
1128
|
+
MATERIAL finish, 27 lights around the bounding box, radiosity from `rad_def.inc`, colour as
|
|
1129
|
+
`rgbf` with filter = 1 − alpha. `ExportPovOptions::camera` ($vpt, $vpr, distance, fov; Python
|
|
1130
|
+
`pov_camera`, 8 numbers) writes OpenSCAD's camera block with **two fixes, both found by rendering
|
|
1131
|
+
in POV-Ray 3.7 and comparing with BelfrySCAD's PNG of the same camera** (they now agree to a
|
|
1132
|
+
pixel): `rotate` comes before `translate`, since the eye orbits `$vpt` (OpenSCAD translates first
|
|
1133
|
+
and frames the wrong place when a view both pans and turns); and the viewport's **vertical** fov
|
|
1134
|
+
becomes POV-Ray's **horizontal** `angle` through an expression on `image_width/image_height`
|
|
1135
|
+
(OpenSCAD writes it across unchanged, zooming its renders in by the aspect ratio). No camera frames
|
|
1136
|
+
the bounding box, as OpenSCAD does without one.
|
|
1123
1137
|
**`writeDxf` is the third 2D writer**, also on `collect2d()`: OpenSCAD's own `export_dxf.cc`
|
|
1124
1138
|
layout verbatim (AC1006 header with the extents, one CONTINUOUS linetype, layer 0, every contour
|
|
1125
1139
|
a closed `LWPOLYLINE` on layer 0 with holes as ordinary contours; 1- and 2-vertex contours as
|
|
@@ -436,14 +436,30 @@ nb::list exportModelPy(const std::string& path, const Geometry& geom, const std:
|
|
|
436
436
|
bool stripSlivers, bool splitComponents, bool splitColors, bool svgFill,
|
|
437
437
|
const std::string& svgFillColor,
|
|
438
438
|
bool svgStroke, const std::string& svgStrokeColor, double svgStrokeWidth,
|
|
439
|
-
nb::object pdfOptions) {
|
|
439
|
+
nb::object pdfOptions, nb::object povCamera) {
|
|
440
440
|
oscadeval::ExportPdfOptions pdf;
|
|
441
441
|
if (!pdfOptions.is_none()) applyPdfOptions(nb::cast<nb::dict>(pdfOptions), pdf);
|
|
442
|
+
oscadeval::ExportPovOptions pov;
|
|
443
|
+
if (!povCamera.is_none()) {
|
|
444
|
+
const std::vector<double> c = nb::cast<std::vector<double>>(povCamera);
|
|
445
|
+
if (c.size() != 8) {
|
|
446
|
+
throw std::runtime_error("pov_camera takes 8 numbers: $vpt x, y, z, $vpr x, y, z, distance, fov");
|
|
447
|
+
}
|
|
448
|
+
oscadeval::ExportPovCamera cam;
|
|
449
|
+
for (int k = 0; k < 3; ++k) {
|
|
450
|
+
cam.vpt[k] = c[k];
|
|
451
|
+
cam.vpr[k] = c[3 + k];
|
|
452
|
+
}
|
|
453
|
+
cam.distance = c[6];
|
|
454
|
+
cam.fov = c[7];
|
|
455
|
+
pov.camera = cam;
|
|
456
|
+
}
|
|
442
457
|
std::vector<std::string> warnings;
|
|
443
458
|
{
|
|
444
459
|
nb::gil_scoped_release rel;
|
|
445
460
|
oscadeval::ExportOptions opts;
|
|
446
461
|
opts.pdf = pdf;
|
|
462
|
+
opts.pov = pov;
|
|
447
463
|
opts.format = format;
|
|
448
464
|
opts.asciiStl = asciiStl;
|
|
449
465
|
opts.stripSlivers = stripSlivers;
|
|
@@ -957,7 +973,7 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
|
957
973
|
nb::arg("svg_fill") = false,
|
|
958
974
|
nb::arg("svg_fill_color") = std::string("white"), nb::arg("svg_stroke") = true,
|
|
959
975
|
nb::arg("svg_stroke_color") = std::string("black"), nb::arg("svg_stroke_width") = 0.35,
|
|
960
|
-
nb::arg("pdf_options") = nb::none(),
|
|
976
|
+
nb::arg("pdf_options") = nb::none(), nb::arg("pov_camera") = nb::none(),
|
|
961
977
|
"Write `geometry` to `path`, format taken from the extension unless `format` says otherwise. "
|
|
962
978
|
"Returns the warnings to surface (open shells, mesh problems, slivers removed) rather than "
|
|
963
979
|
"logging them. Raises RuntimeError when there is no geometry, the format is unknown, or the "
|
|
@@ -976,7 +992,10 @@ NB_MODULE(_openscad_cpp_evaluator, m) {
|
|
|
976
992
|
"(paper-size, orientation, show-scale, show-scale-message, show-grid, grid-size, "
|
|
977
993
|
"show-filename, design-filename, fill, fill-color, stroke, stroke-color, stroke-width, "
|
|
978
994
|
"add-meta-data, title, author, subject, keywords). An unknown key raises rather than "
|
|
979
|
-
"being ignored. .pdf is 2D-only too, and centres the drawing on a fixed paper size
|
|
995
|
+
"being ignored. .pdf is 2D-only too, and centres the drawing on a fixed paper size.\n\n"
|
|
996
|
+
"pov_camera is .pov's camera as 8 numbers -- $vpt x, y, z, $vpr x, y, z, distance, fov -- "
|
|
997
|
+
"so a POV-Ray render frames what the viewport showed. None frames the model from its "
|
|
998
|
+
"bounding box, as OpenSCAD does without a camera.");
|
|
980
999
|
|
|
981
1000
|
m.def("list_fonts", []() {
|
|
982
1001
|
nb::list out;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
#include <array>
|
|
6
6
|
#include <cstdint>
|
|
7
|
+
#include <optional>
|
|
7
8
|
#include <string>
|
|
8
9
|
#include <vector>
|
|
9
10
|
|
|
@@ -233,6 +234,33 @@ std::vector<std::string> writePdf(const std::string& path, const std::vector<Col
|
|
|
233
234
|
|
|
234
235
|
// -- one entry point ------------------------------------------------------
|
|
235
236
|
|
|
237
|
+
// POV-Ray's camera, as OpenSCAD's viewport states it: $vpt, $vpr, $vpd and
|
|
238
|
+
// the field of view. Without one the scene is framed from the model's
|
|
239
|
+
// bounding box, as OpenSCAD frames it when it has no camera to pass.
|
|
240
|
+
struct ExportPovCamera {
|
|
241
|
+
double vpt[3] = {0, 0, 0};
|
|
242
|
+
double vpr[3] = {0, 0, 0};
|
|
243
|
+
double distance = 0;
|
|
244
|
+
double fov = 22.5;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
struct ExportPovOptions {
|
|
248
|
+
std::optional<ExportPovCamera> camera;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// POV-Ray scene description. Every object splitBodiesForExport produces is
|
|
252
|
+
// one mesh2 -- a welded vertex list, a texture per colour, and a texture
|
|
253
|
+
// index per triangle, so per-triangle colour needs no unwelding -- with
|
|
254
|
+
// inside_vector, which makes it a SOLID to POV-Ray (refraction, CSG). That
|
|
255
|
+
// is the difference from OpenSCAD's export_pov.cc, which writes every face
|
|
256
|
+
// as its own flat polygon object. The rest of the scene is OpenSCAD's: its
|
|
257
|
+
// header, MATERIAL finish and ior 1.32 interior, 27 lights around the
|
|
258
|
+
// bounding box, its camera, and radiosity from rad_def.inc. Colour is rgbf
|
|
259
|
+
// with filter = 1 - alpha, as OpenSCAD writes it. Numbers are the shortest
|
|
260
|
+
// text that round-trips, in the classic locale.
|
|
261
|
+
void writePov(const std::string& path, const std::vector<ExportObject>& objects,
|
|
262
|
+
const ExportPovOptions& opts = {});
|
|
263
|
+
|
|
236
264
|
struct ExportOptions {
|
|
237
265
|
// Empty means "decide from the path's extension".
|
|
238
266
|
std::string format;
|
|
@@ -258,6 +286,8 @@ struct ExportOptions {
|
|
|
258
286
|
ExportSvgOptions svg;
|
|
259
287
|
// .pdf only.
|
|
260
288
|
ExportPdfOptions pdf;
|
|
289
|
+
// .pov only.
|
|
290
|
+
ExportPovOptions pov;
|
|
261
291
|
};
|
|
262
292
|
|
|
263
293
|
// Writes `bodies` to `path`, choosing the writer from the extension (or
|
|
@@ -331,7 +331,8 @@ def export_model(path: str, geometry, format: str = "", ascii_stl: bool = False,
|
|
|
331
331
|
split_colors: bool = True,
|
|
332
332
|
svg_fill: bool = False, svg_fill_color: str = "white",
|
|
333
333
|
svg_stroke: bool = True, svg_stroke_color: str = "black",
|
|
334
|
-
svg_stroke_width: float = 0.35, pdf_options: dict | None = None
|
|
334
|
+
svg_stroke_width: float = 0.35, pdf_options: dict | None = None,
|
|
335
|
+
pov_camera=None) -> list:
|
|
335
336
|
"""Write `geometry` to `path`. Returns the warnings to surface.
|
|
336
337
|
|
|
337
338
|
`geometry` is the handle an Evaluator stashes on itself as
|
|
@@ -374,12 +375,17 @@ def export_model(path: str, geometry, format: str = "", ascii_stl: bool = False,
|
|
|
374
375
|
size with nothing to explain it. `.pdf` is 2D-only like `.svg`, and
|
|
375
376
|
centres the drawing on a fixed paper size instead of cutting the page
|
|
376
377
|
to fit.
|
|
378
|
+
|
|
379
|
+
`pov_camera` is `.pov`'s camera as eight numbers -- `$vpt` x, y, z,
|
|
380
|
+
`$vpr` x, y, z, distance, field of view -- so a POV-Ray render frames
|
|
381
|
+
what the viewport showed. None frames the model from its bounding box,
|
|
382
|
+
as OpenSCAD does when it has no camera to pass.
|
|
377
383
|
"""
|
|
378
384
|
try:
|
|
379
385
|
return list(_ext.export_model(path, geometry, format, ascii_stl, strip_slivers,
|
|
380
386
|
split_components, split_colors, svg_fill, svg_fill_color,
|
|
381
387
|
svg_stroke, svg_stroke_color, svg_stroke_width,
|
|
382
|
-
pdf_options))
|
|
388
|
+
pdf_options, pov_camera))
|
|
383
389
|
except Exception as e:
|
|
384
390
|
raise EvalError(str(e)) from e
|
|
385
391
|
|
|
@@ -915,7 +915,8 @@ std::string lowerExtension(const std::string& path) {
|
|
|
915
915
|
}
|
|
916
916
|
|
|
917
917
|
bool isMultiObject(const std::string& ext) {
|
|
918
|
-
return ext == ".3mf" || ext == ".amf" || ext == ".obj" || ext == ".ply" || ext == ".
|
|
918
|
+
return ext == ".3mf" || ext == ".amf" || ext == ".obj" || ext == ".ply" || ext == ".pov" || ext == ".wrl" ||
|
|
919
|
+
ext == ".x3d";
|
|
919
920
|
}
|
|
920
921
|
|
|
921
922
|
// The merged single mesh STL/OFF write, with the open shells kept.
|
|
@@ -1256,6 +1257,159 @@ void writeDxf(const std::string& path, const std::vector<ColoredBody>& bodies) {
|
|
|
1256
1257
|
|
|
1257
1258
|
namespace {
|
|
1258
1259
|
|
|
1260
|
+
// dxfNum's rule for a float: the shortest text that reads back as the same
|
|
1261
|
+
// float. Mesh vertices and colours are floats, and printing them as doubles
|
|
1262
|
+
// would turn 0.1f into 0.100000001490116.
|
|
1263
|
+
std::string floatNum(float v) {
|
|
1264
|
+
if (!std::isfinite(v) || v == 0.0f) return "0";
|
|
1265
|
+
for (int digits = 6; digits <= 9; ++digits) {
|
|
1266
|
+
std::ostringstream o;
|
|
1267
|
+
o.imbue(std::locale::classic());
|
|
1268
|
+
o.precision(digits);
|
|
1269
|
+
o << v;
|
|
1270
|
+
std::istringstream in(o.str());
|
|
1271
|
+
in.imbue(std::locale::classic());
|
|
1272
|
+
float back = 0.0f;
|
|
1273
|
+
in >> back;
|
|
1274
|
+
if (back == v) return o.str();
|
|
1275
|
+
}
|
|
1276
|
+
std::ostringstream o; // unreachable: 9 digits always round-trips a float
|
|
1277
|
+
o.imbue(std::locale::classic());
|
|
1278
|
+
o.precision(9);
|
|
1279
|
+
o << v;
|
|
1280
|
+
return o.str();
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
std::string povVec(double x, double y, double z) {
|
|
1284
|
+
return "<" + dxfNum(x) + ", " + dxfNum(y) + ", " + dxfNum(z) + ">";
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
} // namespace
|
|
1288
|
+
|
|
1289
|
+
void writePov(const std::string& path, const std::vector<ExportObject>& objects, const ExportPovOptions& opts) {
|
|
1290
|
+
std::ofstream out(path);
|
|
1291
|
+
if (!out) throw std::runtime_error("Could not open '" + path + "' for writing");
|
|
1292
|
+
out.imbue(std::locale::classic());
|
|
1293
|
+
|
|
1294
|
+
out << "// Generated by BelfrySCAD (openscad_cpp_evaluator)\n\n"
|
|
1295
|
+
<< "// Camera settings are at the bottom of this script\n\n"
|
|
1296
|
+
<< "#version 3.7;\n"
|
|
1297
|
+
<< "global_settings { assumed_gamma 1.0 }\n"
|
|
1298
|
+
<< "#declare MATERIAL=finish { specular 0.5 roughness 0.001 reflection{0 0.63 fresnel} ambient 0 "
|
|
1299
|
+
"diffuse 0.6 conserve_energy }\n"
|
|
1300
|
+
<< "#declare MATERIAL_INT=interior{ior 1.32}\n";
|
|
1301
|
+
|
|
1302
|
+
const auto rgbf = [](const std::array<float, 4>& c) {
|
|
1303
|
+
return "<" + floatNum(c[0]) + ", " + floatNum(c[1]) + ", " + floatNum(c[2]) + ", " +
|
|
1304
|
+
floatNum(1.0f - c[3]) + ">";
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
bool any = false;
|
|
1308
|
+
double lo[3] = {0, 0, 0}, hi[3] = {0, 0, 0};
|
|
1309
|
+
for (const ExportObject& o : objects) {
|
|
1310
|
+
const size_t vertCount = o.verts.size() / 3;
|
|
1311
|
+
const size_t triCount = o.tris.size() / 3;
|
|
1312
|
+
if (vertCount == 0 || triCount == 0) continue;
|
|
1313
|
+
for (size_t v = 0; v < vertCount; ++v) {
|
|
1314
|
+
for (int k = 0; k < 3; ++k) {
|
|
1315
|
+
const double c = o.verts[v * 3 + k];
|
|
1316
|
+
if (!any) {
|
|
1317
|
+
lo[k] = hi[k] = c;
|
|
1318
|
+
} else {
|
|
1319
|
+
lo[k] = std::min(lo[k], c);
|
|
1320
|
+
hi[k] = std::max(hi[k], c);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
any = true;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// One texture per distinct colour, in order of first use.
|
|
1327
|
+
std::vector<std::array<float, 4>> palette;
|
|
1328
|
+
std::vector<size_t> triTexture(triCount, 0);
|
|
1329
|
+
const auto textureOf = [&](const std::array<float, 4>& c) {
|
|
1330
|
+
for (size_t i = 0; i < palette.size(); ++i) {
|
|
1331
|
+
if (palette[i] == c) return i;
|
|
1332
|
+
}
|
|
1333
|
+
palette.push_back(c);
|
|
1334
|
+
return palette.size() - 1;
|
|
1335
|
+
};
|
|
1336
|
+
for (size_t t = 0; t < triCount; ++t) {
|
|
1337
|
+
triTexture[t] = textureOf(o.triColors.empty() ? o.color : o.triColors[t]);
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
out << "mesh2 {\n vertex_vectors { " << vertCount;
|
|
1341
|
+
for (size_t v = 0; v < vertCount; ++v) {
|
|
1342
|
+
out << ",\n <" << floatNum(o.verts[v * 3]) << ", " << floatNum(o.verts[v * 3 + 1]) << ", "
|
|
1343
|
+
<< floatNum(o.verts[v * 3 + 2]) << ">";
|
|
1344
|
+
}
|
|
1345
|
+
out << "\n }\n texture_list { " << palette.size();
|
|
1346
|
+
for (const std::array<float, 4>& c : palette) {
|
|
1347
|
+
out << "\n texture { pigment { color rgbf " << rgbf(c) << " } finish { MATERIAL } }";
|
|
1348
|
+
}
|
|
1349
|
+
out << "\n }\n face_indices { " << triCount;
|
|
1350
|
+
for (size_t t = 0; t < triCount; ++t) {
|
|
1351
|
+
out << ",\n <" << o.tris[t * 3] << ", " << o.tris[t * 3 + 1] << ", " << o.tris[t * 3 + 2] << ">, "
|
|
1352
|
+
<< triTexture[t];
|
|
1353
|
+
}
|
|
1354
|
+
// inside_vector: without it POV-Ray treats a mesh as a bare surface,
|
|
1355
|
+
// with no inside for the interior (and its ior) or CSG to act on.
|
|
1356
|
+
out << "\n }\n inside_vector <0, 0, 1>\n interior { MATERIAL_INT }\n}\n";
|
|
1357
|
+
}
|
|
1358
|
+
if (!any) throw std::runtime_error("No geometry to export");
|
|
1359
|
+
|
|
1360
|
+
// 27 lights: every combination of {below, centre, above} on each axis,
|
|
1361
|
+
// twice the model's size out, at OpenSCAD's brightness.
|
|
1362
|
+
const double move = 2.0;
|
|
1363
|
+
double at[3][3];
|
|
1364
|
+
for (int k = 0; k < 3; ++k) {
|
|
1365
|
+
const double d = hi[k] - lo[k];
|
|
1366
|
+
at[k][0] = lo[k] - d * move;
|
|
1367
|
+
at[k][1] = (lo[k] + hi[k]) / 2.0;
|
|
1368
|
+
at[k][2] = hi[k] + d * move;
|
|
1369
|
+
}
|
|
1370
|
+
for (double x : at[0]) {
|
|
1371
|
+
for (double y : at[1]) {
|
|
1372
|
+
for (double z : at[2]) {
|
|
1373
|
+
out << "light_source { " << povVec(x, y, z) << " color rgb <0.2, 0.2, 0.2> }\n";
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
if (opts.camera) {
|
|
1379
|
+
// OpenSCAD's camera block, with two fixes, both checked by rendering
|
|
1380
|
+
// in POV-Ray against BelfrySCAD's own image of the same camera:
|
|
1381
|
+
// - rotate BEFORE translate. The eye orbits $vpt, so it is rotated
|
|
1382
|
+
// about the origin and then moved; OpenSCAD translates first,
|
|
1383
|
+
// which rotates $vpt itself away and frames the wrong place
|
|
1384
|
+
// whenever a view both pans and turns.
|
|
1385
|
+
// - the field of view is VERTICAL in the viewport and HORIZONTAL to
|
|
1386
|
+
// POV-Ray's `angle`. OpenSCAD writes it straight across, so its
|
|
1387
|
+
// renders come out zoomed in by the aspect ratio (1.33x at 4:3).
|
|
1388
|
+
// The horizontal angle is left to POV-Ray to work out from the
|
|
1389
|
+
// image it is asked for, so any size frames the same.
|
|
1390
|
+
const ExportPovCamera& c = *opts.camera;
|
|
1391
|
+
out << "camera { look_at <0, 0, 0>\n"
|
|
1392
|
+
<< " location <0, 0, " << dxfNum(c.distance) << ">\n"
|
|
1393
|
+
<< " angle degrees(2 * atan(tan(radians(" << dxfNum(c.fov) << " / 2)) * image_width / image_height))"
|
|
1394
|
+
<< " up <0, 1, 0> right <1, 0, 0> sky <0, 1, 0> right -x*image_width/image_height\n"
|
|
1395
|
+
<< "rotate <" << dxfNum(c.vpr[0]) << ", " << dxfNum(c.vpr[1]) << " + clock * 3, " << dxfNum(c.vpr[2])
|
|
1396
|
+
<< " + clock>\n"
|
|
1397
|
+
<< "translate " << povVec(c.vpt[0], c.vpt[1], c.vpt[2]) << "\n"
|
|
1398
|
+
<< "}\n";
|
|
1399
|
+
} else {
|
|
1400
|
+
const double dx = hi[0] - lo[0], dy = hi[1] - lo[1], dz = hi[2] - lo[2];
|
|
1401
|
+
out << "camera { look_at " << povVec((lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2)
|
|
1402
|
+
<< " location " << povVec(lo[0] + dx * move, lo[1] - dy * move, lo[2] + dz * move)
|
|
1403
|
+
<< " up <0, 0, 1> right <1, 0, 0> sky <0, 0, 1> rotate <-55, clock * 3, clock + 25> right "
|
|
1404
|
+
"x*image_width/image_height }\n";
|
|
1405
|
+
}
|
|
1406
|
+
out << "#include \"rad_def.inc\"\n"
|
|
1407
|
+
<< "global_settings { photons { count 20000 autostop 0 jitter .4 } radiosity { "
|
|
1408
|
+
"Rad_Settings(Radiosity_Normal, off, off) } }\n";
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
namespace {
|
|
1412
|
+
|
|
1259
1413
|
// PDF's own unit is 1/72 inch; models are millimetres.
|
|
1260
1414
|
constexpr double kPtPerMm = 72.0 / 25.4;
|
|
1261
1415
|
// Page margin the ruler is drawn on, in points. OpenSCAD's own MARGIN.
|
|
@@ -1599,7 +1753,7 @@ std::vector<std::string> writePdf(const std::string& path, const std::vector<Col
|
|
|
1599
1753
|
|
|
1600
1754
|
const std::vector<std::string>& exportExtensions() {
|
|
1601
1755
|
static const std::vector<std::string> exts = {".3mf", ".amf", ".dxf", ".pdf", ".stl", ".obj",
|
|
1602
|
-
".off", ".ply", ".svg", ".wrl", ".x3d"};
|
|
1756
|
+
".off", ".ply", ".pov", ".svg", ".wrl", ".x3d"};
|
|
1603
1757
|
return exts;
|
|
1604
1758
|
}
|
|
1605
1759
|
|
|
@@ -1656,6 +1810,8 @@ std::vector<std::string> exportModel(const std::string& path, const std::vector<
|
|
|
1656
1810
|
writeObj(path, objects);
|
|
1657
1811
|
} else if (ext == ".ply") {
|
|
1658
1812
|
writePly(path, objects);
|
|
1813
|
+
} else if (ext == ".pov") {
|
|
1814
|
+
writePov(path, objects, opts.pov);
|
|
1659
1815
|
} else if (ext == ".wrl") {
|
|
1660
1816
|
writeVrml(path, objects);
|
|
1661
1817
|
} else {
|
|
@@ -569,6 +569,124 @@ TEST(ExportDxf, ReachableThroughExportModelAndListedAsAnExtension) {
|
|
|
569
569
|
std::remove(path.c_str());
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
// -- POV-Ray (mesh2) -------------------------------------------------------
|
|
573
|
+
|
|
574
|
+
namespace {
|
|
575
|
+
|
|
576
|
+
std::string povOf(const std::string& code, const std::string& name, const ExportOptions& opts = {}) {
|
|
577
|
+
const std::string path = tempPath(name).string();
|
|
578
|
+
ExportOptions o = opts;
|
|
579
|
+
o.format = ".pov";
|
|
580
|
+
exportModel(path, evalToBodies(code), o);
|
|
581
|
+
const std::string text = readText(path);
|
|
582
|
+
std::remove(path.c_str());
|
|
583
|
+
return text;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// The block following `header` up to and including its matching "}" line --
|
|
587
|
+
// crude, but every block this writer emits closes on a line of its own.
|
|
588
|
+
std::string povBlock(const std::string& text, const std::string& header, size_t from = 0) {
|
|
589
|
+
const size_t at = text.find(header, from);
|
|
590
|
+
if (at == std::string::npos) return "";
|
|
591
|
+
const size_t end = text.find("\n }", at);
|
|
592
|
+
return text.substr(at, end == std::string::npos ? std::string::npos : end - at);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
} // namespace
|
|
596
|
+
|
|
597
|
+
// One mesh2 per exported object -- here one per colour -- with a welded
|
|
598
|
+
// vertex list (a cube is 8 vertices, not 36), 12 triangles, and the
|
|
599
|
+
// inside_vector that makes POV-Ray treat it as a solid rather than a
|
|
600
|
+
// surface. OpenSCAD writes the same scene as 12 separate polygon objects.
|
|
601
|
+
TEST(ExportPov, OneWeldedSolidMesh2PerObject) {
|
|
602
|
+
const std::string text = povOf(
|
|
603
|
+
"color([1, 0.5, 0.25, 0.125]) translate([-10, 0, 0]) cube(10);\n"
|
|
604
|
+
"color(\"green\") translate([10, 0, 0]) cube(10);", "two.pov");
|
|
605
|
+
EXPECT_EQ(countOf(text, "mesh2 {"), 2u);
|
|
606
|
+
EXPECT_EQ(countOf(text, "polygon {"), 0u);
|
|
607
|
+
EXPECT_EQ(countOf(text, "vertex_vectors { 8,"), 2u);
|
|
608
|
+
EXPECT_EQ(countOf(text, "face_indices { 12,"), 2u);
|
|
609
|
+
EXPECT_EQ(countOf(text, "inside_vector <0, 0, 1>"), 2u);
|
|
610
|
+
// rgbf with filter = 1 - alpha, as OpenSCAD writes colour.
|
|
611
|
+
EXPECT_NE(text.find("color rgbf <1, 0.5, 0.25, 0.875>"), std::string::npos);
|
|
612
|
+
EXPECT_NE(text.find("#version 3.7;"), std::string::npos);
|
|
613
|
+
EXPECT_NE(text.find("#include \"rad_def.inc\""), std::string::npos);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Per-triangle colour -- a CSG merge of two colours -- is a texture_list
|
|
617
|
+
// with one entry per colour and a texture index on each triangle. The mesh
|
|
618
|
+
// stays welded; PLY, by contrast, has to unweld to colour a triangle.
|
|
619
|
+
TEST(ExportPov, PerTriangleColourIsATextureIndexNotAnUnweld) {
|
|
620
|
+
const std::string text =
|
|
621
|
+
povOf("color(\"red\") difference() { cube(20, center=true); color(\"blue\") sphere(13, $fn=24); }",
|
|
622
|
+
"tricolor.pov");
|
|
623
|
+
EXPECT_EQ(countOf(text, "mesh2 {"), 1u);
|
|
624
|
+
const std::string textures = povBlock(text, "texture_list {");
|
|
625
|
+
EXPECT_NE(textures.find("texture_list { 2"), std::string::npos);
|
|
626
|
+
EXPECT_NE(textures.find("rgbf <1, 0, 0, 0>"), std::string::npos);
|
|
627
|
+
EXPECT_NE(textures.find("rgbf <0, 0, 1, 0>"), std::string::npos);
|
|
628
|
+
const std::string faces = povBlock(text, "face_indices {");
|
|
629
|
+
EXPECT_NE(faces.find(">, 0"), std::string::npos);
|
|
630
|
+
EXPECT_NE(faces.find(">, 1"), std::string::npos);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Checked by rendering in POV-Ray 3.7 against BelfrySCAD's own PNG of the
|
|
634
|
+
// same camera, which agreed to a pixel. Two departures from OpenSCAD make
|
|
635
|
+
// that true: rotate comes BEFORE translate (the eye orbits $vpt), and the
|
|
636
|
+
// viewport's VERTICAL fov is turned into POV-Ray's HORIZONTAL angle from
|
|
637
|
+
// the image's own aspect ratio.
|
|
638
|
+
TEST(ExportPov, CameraOrbitsVptAndKeepsTheVerticalFieldOfView) {
|
|
639
|
+
ExportOptions opts;
|
|
640
|
+
opts.pov.camera = ExportPovCamera{{0, 5, 5}, {55, 0, 25}, 140, 22.5};
|
|
641
|
+
const std::string text = povOf("cube(10);", "camera.pov", opts);
|
|
642
|
+
const size_t cam = text.find("camera {");
|
|
643
|
+
ASSERT_NE(cam, std::string::npos);
|
|
644
|
+
const std::string block = text.substr(cam, text.find("\n}\n", cam) - cam);
|
|
645
|
+
EXPECT_NE(block.find(" location <0, 0, 140>"), std::string::npos);
|
|
646
|
+
EXPECT_NE(block.find("angle degrees(2 * atan(tan(radians(22.5 / 2)) * image_width / image_height))"),
|
|
647
|
+
std::string::npos);
|
|
648
|
+
const size_t rotate = block.find("rotate <55, 0 + clock * 3, 25 + clock>");
|
|
649
|
+
const size_t translate = block.find("translate <0, 5, 5>");
|
|
650
|
+
ASSERT_NE(rotate, std::string::npos);
|
|
651
|
+
ASSERT_NE(translate, std::string::npos);
|
|
652
|
+
EXPECT_LT(rotate, translate);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
TEST(ExportPov, WithoutACameraFramesTheBoundingBoxAsOpenscadDoes) {
|
|
656
|
+
const std::string text = povOf("translate([-10, 0, 0]) cube([30, 10, 10]);", "nocam.pov");
|
|
657
|
+
EXPECT_NE(text.find("camera { look_at <5, 5, 5> location <50, -20, 20> up <0, 0, 1>"), std::string::npos);
|
|
658
|
+
// 27 lights: below, at and beyond the box on every axis.
|
|
659
|
+
EXPECT_EQ(countOf(text, "light_source {"), 27u);
|
|
660
|
+
EXPECT_NE(text.find("light_source { <-70, -20, -20> color rgb <0.2, 0.2, 0.2> }"), std::string::npos);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
TEST(ExportPov, NumbersIgnoreTheGlobalLocale) {
|
|
664
|
+
const std::locale previous = std::locale::global(std::locale(std::locale::classic(), new GermanishPunct));
|
|
665
|
+
std::string text;
|
|
666
|
+
try {
|
|
667
|
+
text = povOf("translate([0.5, 0, 0]) sphere(10, $fn=64);", "locale.pov");
|
|
668
|
+
} catch (...) {
|
|
669
|
+
std::locale::global(previous);
|
|
670
|
+
throw;
|
|
671
|
+
}
|
|
672
|
+
std::locale::global(previous);
|
|
673
|
+
const std::string verts = povBlock(text, "vertex_vectors {");
|
|
674
|
+
ASSERT_FALSE(verts.empty());
|
|
675
|
+
const int count = std::stoi(verts.substr(std::string("vertex_vectors { ").size()));
|
|
676
|
+
EXPECT_GT(count, 1000); // so grouping would show
|
|
677
|
+
EXPECT_EQ(verts.find('.', 0) < verts.find('\n') ? 1 : 0, 0); // the count has no separator
|
|
678
|
+
EXPECT_EQ(text.find("0,5"), std::string::npos); // no decimal commas anywhere
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
TEST(ExportPov, ReachableThroughExportModelAndListedAsAnExtension) {
|
|
682
|
+
const std::vector<std::string>& exts = exportExtensions();
|
|
683
|
+
EXPECT_NE(std::find(exts.begin(), exts.end(), ".pov"), exts.end());
|
|
684
|
+
const std::string path = tempPath("via_export_model.pov").string();
|
|
685
|
+
EXPECT_TRUE(exportModel(path, evalToBodies("cube(5);"), ExportOptions{}).empty());
|
|
686
|
+
EXPECT_EQ(countOf(readText(path), "mesh2 {"), 1u);
|
|
687
|
+
std::remove(path.c_str());
|
|
688
|
+
}
|
|
689
|
+
|
|
572
690
|
// -- PDF (2D) --------------------------------------------------------------
|
|
573
691
|
|
|
574
692
|
namespace {
|
{openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/tests/test_python_bindings.py
RENAMED
|
@@ -747,6 +747,40 @@ def test_export_model_dxf_refuses_a_3d_model(tmp_path):
|
|
|
747
747
|
export_model(str(tmp_path / "solid.dxf"), ev.geometry)
|
|
748
748
|
|
|
749
749
|
|
|
750
|
+
def test_export_model_writes_pov_mesh2_with_the_viewport_camera(tmp_path):
|
|
751
|
+
""".pov through the facade: one solid mesh2 per object, and pov_camera
|
|
752
|
+
($vpt, $vpr, distance, fov) reaching the camera block."""
|
|
753
|
+
from openscad_cpp_evaluator import Evaluator, export_extensions, export_model
|
|
754
|
+
|
|
755
|
+
assert ".pov" in export_extensions()
|
|
756
|
+
src = tmp_path / "scene.scad"
|
|
757
|
+
src.write_text('color("red") cube(10); color("green") translate([20, 0, 0]) cube(10);')
|
|
758
|
+
ev = Evaluator()
|
|
759
|
+
ev.evaluate(str(src), {})
|
|
760
|
+
|
|
761
|
+
out = tmp_path / "scene.pov"
|
|
762
|
+
assert export_model(str(out), ev.geometry, pov_camera=[1, 2, 3, 55, 0, 25, 140, 22.5]) == []
|
|
763
|
+
text = out.read_text()
|
|
764
|
+
assert text.count("mesh2 {") == 2 and text.count("inside_vector <0, 0, 1>") == 2
|
|
765
|
+
assert "rotate <55, 0 + clock * 3, 25 + clock>\ntranslate <1, 2, 3>" in text
|
|
766
|
+
assert "location <0, 0, 140>" in text
|
|
767
|
+
|
|
768
|
+
bare = tmp_path / "bare.pov"
|
|
769
|
+
export_model(str(bare), ev.geometry)
|
|
770
|
+
assert "rotate <-55, clock * 3, clock + 25>" in bare.read_text() # the bounding-box camera
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
def test_export_model_pov_camera_needs_eight_numbers(tmp_path):
|
|
774
|
+
from openscad_cpp_evaluator import Evaluator, EvalError, export_model
|
|
775
|
+
|
|
776
|
+
src = tmp_path / "c.scad"
|
|
777
|
+
src.write_text("cube(1);")
|
|
778
|
+
ev = Evaluator()
|
|
779
|
+
ev.evaluate(str(src), {})
|
|
780
|
+
with pytest.raises(EvalError, match="8 numbers"):
|
|
781
|
+
export_model(str(tmp_path / "c.pov"), ev.geometry, pov_camera=[0, 0, 0])
|
|
782
|
+
|
|
783
|
+
|
|
750
784
|
def test_export_model_writes_pdf_and_takes_its_options(tmp_path):
|
|
751
785
|
""".pdf through the facade, plus the option dict. Same
|
|
752
786
|
two-parameter-list trap as split_components and the svg_* set."""
|
|
File without changes
|
{openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.32.0 → openscad_cpp_evaluator-1.33.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|