openscad-cpp-evaluator 0.55.2__tar.gz → 0.55.4__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-0.55.2 → openscad_cpp_evaluator-0.55.4}/CLAUDE.md +9 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/bytecode_vm.hpp +3 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/colored_body.hpp +16 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/python/openscad_cpp_evaluator/__init__.py +2 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/booleans.cpp +47 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/transforms.cpp +4 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/bytecode_compiler.cpp +15 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/bytecode_vm.cpp +6 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/colored_body.cpp +11 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/export.cpp +1 -1
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_booleans.cpp +118 -10
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_control_flow.cpp +6 -6
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_export.cpp +4 -2
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/README.md +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/uv.lock +0 -0
|
@@ -231,6 +231,15 @@ top-level 2D primitive/projection() script had been silently unexportable via th
|
|
|
231
231
|
Fixed by porting `toRenderableBodies()` (`colored_body.hpp`/`.cpp`) and calling it from the CLI right
|
|
232
232
|
before export, matching the reference's own call site exactly.
|
|
233
233
|
|
|
234
|
+
`ColoredBody::sectionZ` rides alongside for the same reason. A `manifold::CrossSection` is purely
|
|
235
|
+
2D, so `down(1) square(10)` had nowhere to put the `-1` and silently dropped it — and that is not
|
|
236
|
+
cosmetic: BOSL2 layers 2D overlays by pushing one down (isosurface's `contour()` Example 1 puts a
|
|
237
|
+
blue backdrop below a green contour), and with the offset lost the two slabs became exactly
|
|
238
|
+
coplanar, z-fought, and whichever drew last covered the other completely. `generateTransform`
|
|
239
|
+
accumulates the z of any `translate` applied to a section, and `toRenderableBodies()` translates the
|
|
240
|
+
extruded slab by it. Only translation is carried — a 2D shape under a 3D *rotation* still loses it,
|
|
241
|
+
which would need a full matrix per section and nothing has asked for that yet.
|
|
242
|
+
|
|
234
243
|
**Font support**: a `FontProvider` abstract interface (`font_provider.hpp`: `resolveFont`/
|
|
235
244
|
`metrics`/`shapeText`/`glyphInkBounds`/`glyphOutline`) with `FreetypeFontProvider` as the built-in
|
|
236
245
|
implementation everything here actually uses. `Evaluator`'s constructor takes an optional
|
|
@@ -68,6 +68,9 @@ struct PendingCsgWrap {
|
|
|
68
68
|
std::uint64_t randsBefore = 0;
|
|
69
69
|
int siteIdx = -1;
|
|
70
70
|
std::vector<Value> groupSizes;
|
|
71
|
+
// Parallel to groupSizes: whether a group that came out EMPTY is still
|
|
72
|
+
// an operand. See Op::CsgGroupEnd's `a`.
|
|
73
|
+
std::vector<Value> emptyIsAGroup;
|
|
71
74
|
size_t groupStartSize = 0;
|
|
72
75
|
};
|
|
73
76
|
|
|
@@ -24,6 +24,21 @@ struct ColoredBody {
|
|
|
24
24
|
std::optional<std::array<float, 4>> color; // RGBA; nullopt = "no explicit color() -- follow the live theme"
|
|
25
25
|
std::optional<manifold::CrossSection> section;
|
|
26
26
|
bool flatPreview = false;
|
|
27
|
+
|
|
28
|
+
// Where a 2D `section` sits along Z. Only meaningful while `section` is
|
|
29
|
+
// set, and applied when toRenderableBodies() extrudes it.
|
|
30
|
+
//
|
|
31
|
+
// A manifold::CrossSection is purely 2D, so `down(1) square(10)` had
|
|
32
|
+
// nowhere to put the -1 and silently dropped it. That is not merely
|
|
33
|
+
// cosmetic: BOSL2 layers 2D overlays by pushing one down (isosurface's
|
|
34
|
+
// contour() Example 1 puts a blue backdrop below a green contour), and
|
|
35
|
+
// with the offset lost the two slabs became exactly coplanar, z-fought,
|
|
36
|
+
// and whichever was drawn last covered the other completely.
|
|
37
|
+
//
|
|
38
|
+
// Only translation is carried. A 2D shape under a 3D ROTATION still
|
|
39
|
+
// loses it -- representing that needs a full matrix per section, which
|
|
40
|
+
// nothing has asked for yet.
|
|
41
|
+
double sectionZ = 0.0;
|
|
27
42
|
BodyRole role = BodyRole::Normal;
|
|
28
43
|
std::optional<std::vector<std::array<float, 4>>> triColors; // per-triangle RGBA, multi-color CSG merges only
|
|
29
44
|
|
|
@@ -60,7 +75,7 @@ Value colorToValue(const std::optional<std::array<double, 4>>& color);
|
|
|
60
75
|
std::optional<std::array<float, 4>> valueToColor(const Value& v);
|
|
61
76
|
|
|
62
77
|
// Converts every top-level 2D-only result (`body` unset, `section` set --
|
|
63
|
-
// e.g. a bare `circle();`) into a
|
|
78
|
+
// e.g. a bare `circle();`) into a 1-unit-tall extruded Manifold
|
|
64
79
|
// tagged `flatPreview = true`, so a mesh exporter/renderer that only
|
|
65
80
|
// understands 3D Manifolds (writeStl/writeObj/writeOff/writeThreeMf) can
|
|
66
81
|
// still show a 2D top-level result instead of silently dropping it. 3D
|
|
@@ -213,7 +213,8 @@ def _summarize_param(value, max_items: int = 6, max_len: int = 40) -> str:
|
|
|
213
213
|
# Params keys never shown in format_csg_tree's per-node summary, regardless
|
|
214
214
|
# of kind -- pure internal bookkeeping or already represented structurally
|
|
215
215
|
# elsewhere in the tree. Mirrors the reference's _DUMP_HIDDEN_PARAM_KEYS.
|
|
216
|
-
_DUMP_HIDDEN_PARAM_KEYS = frozenset(
|
|
216
|
+
_DUMP_HIDDEN_PARAM_KEYS = frozenset(
|
|
217
|
+
{"color", "op", "name", "group_sizes", "empty_is_a_group"})
|
|
217
218
|
|
|
218
219
|
# Auto-generated tessellation data (not user-authored) for every kind except
|
|
219
220
|
# polyhedron, where the equivalent data *is* the user's own points/faces.
|
|
@@ -108,16 +108,43 @@ CSGParams resolveCsg(Evaluator& ev, const oscad::ModularCall& node, EvalContext&
|
|
|
108
108
|
if (!assignNodes.empty()) ev.evalChildren(assignNodes, blockCtx);
|
|
109
109
|
|
|
110
110
|
std::vector<Value> groupSizes;
|
|
111
|
+
std::vector<Value> emptyIsAGroup;
|
|
111
112
|
groupSizes.reserve(geoNodes.size());
|
|
113
|
+
emptyIsAGroup.reserve(geoNodes.size());
|
|
112
114
|
for (const oscad::ASTNode* geoNode : geoNodes) {
|
|
113
115
|
const size_t before = ev.currentTreeFrameSize();
|
|
114
116
|
ev.evalChildren(std::vector<const oscad::ASTNode*>{geoNode}, blockCtx);
|
|
115
117
|
groupSizes.push_back(Value{static_cast<double>(ev.currentTreeFrameSize() - before)});
|
|
118
|
+
// Whether a statement that produced NOTHING still counts as an
|
|
119
|
+
// operand.
|
|
120
|
+
//
|
|
121
|
+
// The reference builds a node for a module instantiation and for a
|
|
122
|
+
// loop whatever they contain, so an empty one is an empty operand
|
|
123
|
+
// and annihilates an intersection. An `if` that takes no branch, a
|
|
124
|
+
// bare block, and a `*`-disabled statement build no node at all, so
|
|
125
|
+
// they are not operands and must be skipped.
|
|
126
|
+
//
|
|
127
|
+
// Every line of this was checked against OpenSCAD rather than
|
|
128
|
+
// reasoned about -- `intersection(){ cube(10); X; }` keeps the cube
|
|
129
|
+
// for `if(false) sphere(6)`, `{ }` and `*cube(1)`, and comes out
|
|
130
|
+
// empty for `for(i=[1:0]) sphere(6)`, `union(){}`, `group(){}` and
|
|
131
|
+
// a call to an empty user module.
|
|
132
|
+
const oscad::NodeKind k = geoNode->kind();
|
|
133
|
+
emptyIsAGroup.push_back(Value{
|
|
134
|
+
k == oscad::NodeKind::ModularCall ||
|
|
135
|
+
k == oscad::NodeKind::ModularFor ||
|
|
136
|
+
k == oscad::NodeKind::ModularIntersectionFor ||
|
|
137
|
+
k == oscad::NodeKind::ModularLet ||
|
|
138
|
+
k == oscad::NodeKind::ModularModifierShowOnly ||
|
|
139
|
+
k == oscad::NodeKind::ModularModifierHighlight ||
|
|
140
|
+
k == oscad::NodeKind::ModularModifierBackground});
|
|
116
141
|
}
|
|
117
142
|
|
|
118
143
|
CSGParams params;
|
|
119
144
|
params["op"] = Value{op};
|
|
120
145
|
params["group_sizes"] = Value{std::make_shared<const ValueList>(ValueList{std::move(groupSizes)})};
|
|
146
|
+
params["empty_is_a_group"] =
|
|
147
|
+
Value{std::make_shared<const ValueList>(ValueList{std::move(emptyIsAGroup)})};
|
|
121
148
|
return params;
|
|
122
149
|
}
|
|
123
150
|
|
|
@@ -180,16 +207,36 @@ std::vector<ColoredBody> generateCsg(Evaluator& ev, const CSGParams& params, con
|
|
|
180
207
|
const oscad::ASTNode&) {
|
|
181
208
|
const std::string& op = std::get<std::string>(params.at("op"));
|
|
182
209
|
const auto& groupSizes = std::get<ListPtr>(params.at("group_sizes"))->items;
|
|
210
|
+
const auto emptyIsAGroupIt = params.find("empty_is_a_group");
|
|
211
|
+
const std::vector<Value>* emptyIsAGroup =
|
|
212
|
+
emptyIsAGroupIt == params.end()
|
|
213
|
+
? nullptr
|
|
214
|
+
: &std::get<ListPtr>(emptyIsAGroupIt->second)->items;
|
|
183
215
|
|
|
184
216
|
std::vector<ColoredBody> allBg, allHi, allSo, allDo;
|
|
185
217
|
std::optional<ColoredBody> csgResult;
|
|
186
218
|
size_t idx = 0;
|
|
187
219
|
|
|
220
|
+
size_t stmtIndex = 0;
|
|
188
221
|
for (const Value& sizeVal : groupSizes) {
|
|
189
222
|
const size_t size = static_cast<size_t>(std::get<double>(sizeVal));
|
|
223
|
+
const size_t thisStmt = stmtIndex++;
|
|
190
224
|
std::vector<ColoredBody> stmtBodies = flattenCsgTree(children, idx, size);
|
|
191
225
|
idx += size;
|
|
192
226
|
|
|
227
|
+
// A statement that built no CSG node at all is not an operand --
|
|
228
|
+
// an `if` whose branch was not taken, or an empty block. Only a
|
|
229
|
+
// for-loop still counts as one when it produced nothing, matching
|
|
230
|
+
// the group node the reference builds for it regardless. Without
|
|
231
|
+
// this, `intersection(){ X; if (crop) Y; }` -- BOSL2's hirth()
|
|
232
|
+
// among others -- came out empty whenever the condition was false.
|
|
233
|
+
if (size == 0) {
|
|
234
|
+
const bool isGroup = emptyIsAGroup && thisStmt < emptyIsAGroup->size() &&
|
|
235
|
+
std::holds_alternative<bool>((*emptyIsAGroup)[thisStmt]) &&
|
|
236
|
+
std::get<bool>((*emptyIsAGroup)[thisStmt]);
|
|
237
|
+
if (!isGroup) continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
193
240
|
RoleSplit split = splitByRole(stmtBodies);
|
|
194
241
|
allBg.insert(allBg.end(), split.background.begin(), split.background.end());
|
|
195
242
|
allHi.insert(allHi.end(), split.highlight.begin(), split.highlight.end());
|
|
@@ -233,6 +233,10 @@ std::vector<ColoredBody> generateTransform(Evaluator&, const CSGParams& params,
|
|
|
233
233
|
std::vector<ColoredBody> result;
|
|
234
234
|
for (ColoredBody b : flattenCsgTree(children)) {
|
|
235
235
|
if (b.section) {
|
|
236
|
+
// The CrossSection takes x/y; z has nowhere to go in it, so it
|
|
237
|
+
// rides along on the body until the section is extruded. See
|
|
238
|
+
// ColoredBody::sectionZ.
|
|
239
|
+
if (name == "translate") b.sectionZ += toVec3(getArg(args, 0, "v", Value{})).z;
|
|
236
240
|
b.section = applyTransform2d(name, args, std::move(*b.section));
|
|
237
241
|
} else if (b.body) {
|
|
238
242
|
b.body = applyTransform3d(name, args, std::move(*b.body));
|
|
@@ -1348,7 +1348,21 @@ public:
|
|
|
1348
1348
|
}
|
|
1349
1349
|
out.push_back({Op::CsgGroupStart, 0, 0, nullptr});
|
|
1350
1350
|
compileStatementList(std::vector<const oscad::ASTNode*>{geoNode}, out);
|
|
1351
|
-
out
|
|
1351
|
+
// `a` = whether a group that turns out EMPTY is still an
|
|
1352
|
+
// operand: a module instantiation or a loop builds a node
|
|
1353
|
+
// whatever it contains, an `if`/block/`*` does not. Mirrors
|
|
1354
|
+
// resolveCsg's own "empty_is_a_group" (booleans.cpp), where the
|
|
1355
|
+
// full reasoning and the OpenSCAD checks live.
|
|
1356
|
+
const oscad::NodeKind k = geoNode->kind();
|
|
1357
|
+
const int emptyIsAGroup = (
|
|
1358
|
+
k == oscad::NodeKind::ModularCall ||
|
|
1359
|
+
k == oscad::NodeKind::ModularFor ||
|
|
1360
|
+
k == oscad::NodeKind::ModularIntersectionFor ||
|
|
1361
|
+
k == oscad::NodeKind::ModularLet ||
|
|
1362
|
+
k == oscad::NodeKind::ModularModifierShowOnly ||
|
|
1363
|
+
k == oscad::NodeKind::ModularModifierHighlight ||
|
|
1364
|
+
k == oscad::NodeKind::ModularModifierBackground) ? 1 : 0;
|
|
1365
|
+
out.push_back({Op::CsgGroupEnd, emptyIsAGroup, 0, nullptr});
|
|
1352
1366
|
}
|
|
1353
1367
|
out.push_back({Op::CloseExprScope, 0, 0, nullptr});
|
|
1354
1368
|
out.push_back({Op::PopCsgWrap, idx, 0, &call.position()});
|
|
@@ -1311,7 +1311,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1311
1311
|
// ITERATION child ctxs are pushed separately, by the
|
|
1312
1312
|
// compiled loop's own Op::ForIterNext.
|
|
1313
1313
|
ev.treeStack_.emplace_back();
|
|
1314
|
-
f.csgWrapStack.push_back({site.op, randsBefore, ins.a, {}, 0});
|
|
1314
|
+
f.csgWrapStack.push_back({site.op, randsBefore, ins.a, {}, {}, 0});
|
|
1315
1315
|
++f.pc;
|
|
1316
1316
|
break;
|
|
1317
1317
|
}
|
|
@@ -1336,6 +1336,8 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1336
1336
|
ev.evalChildren(std::vector<const oscad::ASTNode*>{stmt}, ctx);
|
|
1337
1337
|
pending.groupSizes.push_back(
|
|
1338
1338
|
Value{static_cast<double>(ev.treeStack_.back().size() - before)});
|
|
1339
|
+
// A spliced child is a plain statement, never a loop.
|
|
1340
|
+
pending.emptyIsAGroup.push_back(Value{false});
|
|
1339
1341
|
}
|
|
1340
1342
|
++f.pc;
|
|
1341
1343
|
break;
|
|
@@ -1344,6 +1346,7 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1344
1346
|
PendingCsgWrap& pending = f.csgWrapStack.back();
|
|
1345
1347
|
const size_t after = ev.treeStack_.back().size();
|
|
1346
1348
|
pending.groupSizes.push_back(Value{static_cast<double>(after - pending.groupStartSize)});
|
|
1349
|
+
pending.emptyIsAGroup.push_back(Value{ins.a != 0});
|
|
1347
1350
|
++f.pc;
|
|
1348
1351
|
break;
|
|
1349
1352
|
}
|
|
@@ -1367,6 +1370,8 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
1367
1370
|
if (site.includeOpParam) params["op"] = Value{pending.op};
|
|
1368
1371
|
params["group_sizes"] =
|
|
1369
1372
|
Value{std::make_shared<const ValueList>(ValueList{std::move(pending.groupSizes)})};
|
|
1373
|
+
params["empty_is_a_group"] = Value{std::make_shared<const ValueList>(
|
|
1374
|
+
ValueList{std::move(pending.emptyIsAGroup)})};
|
|
1370
1375
|
// Mirrors Evaluator::buildTreeNode's own post-
|
|
1371
1376
|
// resolveBody() half exactly (csg_resolve.cpp).
|
|
1372
1377
|
const bool uncacheable =
|
|
@@ -21,7 +21,13 @@ std::optional<std::array<float, 4>> valueToColor(const Value& v) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
namespace {
|
|
24
|
-
|
|
24
|
+
// The reference extrudes a 2D shape to exactly 1 unit for preview -- measured
|
|
25
|
+
// against OpenSCAD at three camera tilts (60/70/80 degrees), which put it at
|
|
26
|
+
// 0.92/1.00/0.99, the 60 being pixel-rounding on the shallowest angle. Ours
|
|
27
|
+
// was 1e-3, which reads as a flat silhouette with no visible edge and, more
|
|
28
|
+
// annoyingly, gives --viewall a different bounding box to fit, so every 2D
|
|
29
|
+
// docs image came out at a different scale from the published one.
|
|
30
|
+
constexpr double kTopLevel2dHeight = 1.0;
|
|
25
31
|
} // namespace
|
|
26
32
|
|
|
27
33
|
std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodies) {
|
|
@@ -31,6 +37,10 @@ std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodi
|
|
|
31
37
|
if (!cb.body && cb.section) {
|
|
32
38
|
ColoredBody flat;
|
|
33
39
|
flat.body = manifold::Manifold::Extrude(cb.section->ToPolygons(), kTopLevel2dHeight);
|
|
40
|
+
// Put it back where a 3D translate moved it -- the CrossSection
|
|
41
|
+
// could not hold that. See ColoredBody::sectionZ.
|
|
42
|
+
if (cb.sectionZ != 0.0)
|
|
43
|
+
flat.body = flat.body->Translate(manifold::vec3(0, 0, cb.sectionZ));
|
|
34
44
|
flat.color = cb.color;
|
|
35
45
|
flat.flatPreview = true;
|
|
36
46
|
flat.role = cb.role;
|
|
@@ -432,7 +432,7 @@ std::vector<ExportObject> splitBodiesForExport(const std::vector<ColoredBody>& b
|
|
|
432
432
|
// A `flatPreview` body is a top-level 2D shape thin-extruded so it can be
|
|
433
433
|
// SEEN (toRenderableBodies). The top level keeps 2D and 3D side by side
|
|
434
434
|
// for exactly that reason -- but a mesh export of a mixed script must
|
|
435
|
-
// not smuggle a
|
|
435
|
+
// not smuggle a 1-unit-tall slab in beside the real solids, which is what
|
|
436
436
|
// the reference drops there too. A 2D-ONLY script still exports its
|
|
437
437
|
// slab, unchanged: that is the only geometry there is, and dropping it
|
|
438
438
|
// would leave nothing to write.
|
|
@@ -40,11 +40,76 @@ TEST(Intersection, KeepsOnlyOverlappingVolume) {
|
|
|
40
40
|
EXPECT_NEAR(e.bodies[0].body->Volume(), 1.0, 1e-6);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
TEST(Intersection,
|
|
43
|
+
TEST(Intersection, ADisabledStatementIsNotAnOperandAtAll) {
|
|
44
|
+
// `*cube(1)` produces no CSGNode, so it is not an operand -- the
|
|
45
|
+
// intersection has one child and returns it. This used to assert an
|
|
46
|
+
// EMPTY result on the reasoning that a statement contributing no bodies
|
|
47
|
+
// is "intersection with nothing"; checking against OpenSCAD showed that
|
|
48
|
+
// is wrong (it gives volume 8, the cube(2)), and the same mistake is
|
|
49
|
+
// what made BOSL2's hirth() render nothing at all: its geometry is
|
|
50
|
+
// `intersection(){ ...; if (crop) tube(...); }` and crop defaults false.
|
|
44
51
|
Evaluated e = evalSrc("intersection() { cube(2); *cube(1); }");
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
53
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
TEST(Intersection, AnUntakenIfIsNotAnOperandEither) {
|
|
57
|
+
// The reported case, reduced. Verified against OpenSCAD: volume 1000.
|
|
58
|
+
Evaluated e = evalSrc("intersection() { cube(10); if (false) sphere(6); }");
|
|
59
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
60
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 1000.0, 1e-6);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
TEST(Intersection, EmptyStatementsFollowTheReferenceExactly) {
|
|
64
|
+
// Every row checked against OpenSCAD, not reasoned about. The rule that
|
|
65
|
+
// falls out: a module instantiation or a loop builds a node whatever it
|
|
66
|
+
// contains, so an empty one is an empty operand and annihilates; an
|
|
67
|
+
// `if` with no branch taken, a bare block and a `*`-disabled statement
|
|
68
|
+
// build no node at all and are not operands.
|
|
69
|
+
struct Case { const char* stmt; bool keepsTheCube; };
|
|
70
|
+
const Case cases[] = {
|
|
71
|
+
{"if (false) sphere(6);", true},
|
|
72
|
+
{"{ }", true},
|
|
73
|
+
{"*cube(1);", true},
|
|
74
|
+
{"for (i = [1:0]) sphere(6);", false},
|
|
75
|
+
{"union() { }", false},
|
|
76
|
+
{"group() { }", false},
|
|
77
|
+
{"let(x = 1) { }", false},
|
|
78
|
+
{"#union() { }", false},
|
|
79
|
+
};
|
|
80
|
+
for (const Case& c : cases) {
|
|
81
|
+
const std::string src =
|
|
82
|
+
std::string("intersection() { cube(10, center=true); ") + c.stmt + " }";
|
|
83
|
+
Evaluated e = evalSrc(src);
|
|
84
|
+
if (c.keepsTheCube) {
|
|
85
|
+
ASSERT_EQ(e.bodies.size(), 1u) << src;
|
|
86
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 1000.0, 1e-6) << src;
|
|
87
|
+
} else {
|
|
88
|
+
const bool anyVolume = std::any_of(
|
|
89
|
+
e.bodies.begin(), e.bodies.end(),
|
|
90
|
+
[](const ColoredBody& b) { return b.body && !b.body->IsEmpty(); });
|
|
91
|
+
EXPECT_FALSE(anyVolume) << src;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
TEST(Intersection, AnEmptyUserModuleIsStillAnOperand) {
|
|
97
|
+
// The reference builds a node for a module instantiation whatever the
|
|
98
|
+
// module's body does, so calling one that draws nothing empties the
|
|
99
|
+
// intersection. Verified against OpenSCAD (writes no STL).
|
|
100
|
+
Evaluated e = evalSrc("module m() { } intersection() { cube(10); m(); }");
|
|
101
|
+
const bool anyVolume = std::any_of(
|
|
102
|
+
e.bodies.begin(), e.bodies.end(),
|
|
103
|
+
[](const ColoredBody& b) { return b.body && !b.body->IsEmpty(); });
|
|
104
|
+
EXPECT_FALSE(anyVolume);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
TEST(Intersection, AnEmptyForLoopIsStillAnOperand) {
|
|
108
|
+
// The one empty statement that DOES annihilate: the reference builds a
|
|
109
|
+
// group node for a for-loop however many times it iterates, so an empty
|
|
110
|
+
// one is an empty operand. Verified against OpenSCAD, which writes no
|
|
111
|
+
// STL at all for this.
|
|
112
|
+
Evaluated e = evalSrc("intersection() { cube(10); for (i = [1:0]) sphere(6); }");
|
|
48
113
|
EXPECT_TRUE(e.bodies.empty());
|
|
49
114
|
}
|
|
50
115
|
|
|
@@ -73,14 +138,19 @@ TEST(Union, MultipleBodiesInFirstStatementAllSurvive) {
|
|
|
73
138
|
EXPECT_NEAR(e.bodies[0].body->Volume(), 20.0, 1e-6);
|
|
74
139
|
}
|
|
75
140
|
|
|
76
|
-
TEST(Intersection,
|
|
141
|
+
TEST(Intersection, ADisabledFirstStatementLetsTheNextOneLead) {
|
|
142
|
+
// Verified against OpenSCAD: volume 8, not empty.
|
|
77
143
|
Evaluated e = evalSrc("intersection() { *cube(10); cube(2); }");
|
|
78
|
-
|
|
144
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
145
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
|
|
79
146
|
}
|
|
80
147
|
|
|
81
|
-
TEST(Difference,
|
|
148
|
+
TEST(Difference, ADisabledFirstStatementLetsTheNextOneBecomeTheBase) {
|
|
149
|
+
// Verified against OpenSCAD: volume 8 -- cube(2) becomes the base
|
|
150
|
+
// rather than the difference collapsing to nothing.
|
|
82
151
|
Evaluated e = evalSrc("difference() { *cube(10); cube(2); }");
|
|
83
|
-
|
|
152
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
153
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
|
|
84
154
|
}
|
|
85
155
|
|
|
86
156
|
TEST(Difference, EmptySubtractorLeavesBaseUnchanged) {
|
|
@@ -625,7 +695,7 @@ TEST(MixedDimensions, TopLevelWarnsButKeepsBothDimensions) {
|
|
|
625
695
|
|
|
626
696
|
TEST(MixedDimensions, ExportDropsTheFlatSlabWhenRealSolidsArePresent) {
|
|
627
697
|
// The top level keeps a 2D shape so it can be SEEN, thin-extruded by
|
|
628
|
-
// toRenderableBodies. A mesh export must not smuggle that
|
|
698
|
+
// toRenderableBodies. A mesh export must not smuggle that 1-unit-tall slab
|
|
629
699
|
// in beside the real solids -- the reference drops it there too.
|
|
630
700
|
Evaluated e = evalSrc("square(4); cube(1);");
|
|
631
701
|
const std::vector<ColoredBody> renderable = toRenderableBodies(e.bodies);
|
|
@@ -633,7 +703,7 @@ TEST(MixedDimensions, ExportDropsTheFlatSlabWhenRealSolidsArePresent) {
|
|
|
633
703
|
|
|
634
704
|
const std::vector<ExportObject> objects = splitBodiesForExport(renderable, nullptr);
|
|
635
705
|
ASSERT_EQ(objects.size(), 1u) << "but only the cube is exported";
|
|
636
|
-
//
|
|
706
|
+
// Only the cube survives, so the height is the cube's own.
|
|
637
707
|
float zmin = 1e9f, zmax = -1e9f;
|
|
638
708
|
for (size_t i = 2; i < objects[0].verts.size(); i += 3) {
|
|
639
709
|
zmin = std::min(zmin, objects[0].verts[i]);
|
|
@@ -651,6 +721,44 @@ TEST(MixedDimensions, ExportKeepsTheFlatSlabWhenItIsTheOnlyGeometry) {
|
|
|
651
721
|
EXPECT_EQ(objects.size(), 1u);
|
|
652
722
|
}
|
|
653
723
|
|
|
724
|
+
TEST(MixedDimensions, ATranslatedTwoDeeShapeKeepsItsZ) {
|
|
725
|
+
// A CrossSection is purely 2D, so `translate([0,0,-1]) square(10)` had
|
|
726
|
+
// nowhere to put the -1 and dropped it. Two 2D shapes meant to be
|
|
727
|
+
// layered then came out exactly coplanar, z-fought, and whichever drew
|
|
728
|
+
// last hid the other -- BOSL2's isosurface contour() Example 1 renders a
|
|
729
|
+
// green contour over a blue backdrop pushed down by 1, and the backdrop
|
|
730
|
+
// covered the contour completely.
|
|
731
|
+
Evaluated e = evalSrc("translate([0,0,-1]) square(10, center=true);");
|
|
732
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
733
|
+
ASSERT_TRUE(e.bodies[0].section.has_value());
|
|
734
|
+
EXPECT_DOUBLE_EQ(e.bodies[0].sectionZ, -1.0);
|
|
735
|
+
|
|
736
|
+
const std::vector<ColoredBody> renderable = toRenderableBodies(e.bodies);
|
|
737
|
+
ASSERT_EQ(renderable.size(), 1u);
|
|
738
|
+
ASSERT_TRUE(renderable[0].body.has_value());
|
|
739
|
+
const manifold::Box box = renderable[0].body->BoundingBox();
|
|
740
|
+
EXPECT_NEAR(box.min.z, -1.0, 1e-9) << "the extruded slab sits where it was moved to";
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
TEST(MixedDimensions, TwoDeeZOffsetsAccumulateAndDefaultToZero) {
|
|
744
|
+
Evaluated flat = evalSrc("square(10);");
|
|
745
|
+
ASSERT_EQ(flat.bodies.size(), 1u);
|
|
746
|
+
EXPECT_DOUBLE_EQ(flat.bodies[0].sectionZ, 0.0);
|
|
747
|
+
|
|
748
|
+
Evaluated stacked = evalSrc(
|
|
749
|
+
"translate([0,0,2]) translate([0,0,3]) square(10);");
|
|
750
|
+
ASSERT_EQ(stacked.bodies.size(), 1u);
|
|
751
|
+
EXPECT_DOUBLE_EQ(stacked.bodies[0].sectionZ, 5.0);
|
|
752
|
+
|
|
753
|
+
// x/y still go into the CrossSection itself, not the offset.
|
|
754
|
+
Evaluated moved = evalSrc("translate([4,5,6]) square(10);");
|
|
755
|
+
ASSERT_EQ(moved.bodies.size(), 1u);
|
|
756
|
+
EXPECT_DOUBLE_EQ(moved.bodies[0].sectionZ, 6.0);
|
|
757
|
+
const manifold::Rect r = moved.bodies[0].section->Bounds();
|
|
758
|
+
EXPECT_NEAR(r.min.x, 4.0, 1e-9);
|
|
759
|
+
EXPECT_NEAR(r.min.y, 5.0, 1e-9);
|
|
760
|
+
}
|
|
761
|
+
|
|
654
762
|
TEST(MixedDimensions, UniformChildrenAreUntouched) {
|
|
655
763
|
EXPECT_TRUE(dimWarnings("union() { cube(1); cube(2); }").empty());
|
|
656
764
|
EXPECT_TRUE(dimWarnings("union() { square(1); square(2); }").empty());
|
|
@@ -845,15 +845,15 @@ TEST(ExprEvalFunctionCall, CallingANonFunctionVariableWarnsAndIsUndef) {
|
|
|
845
845
|
EXPECT_NE(warnings.back().find("Ignoring unknown function 'x'"), std::string::npos);
|
|
846
846
|
}
|
|
847
847
|
|
|
848
|
-
TEST(Intersection,
|
|
849
|
-
//
|
|
850
|
-
//
|
|
851
|
-
//
|
|
852
|
-
// resolve still fires even though the final result has zero bodies.
|
|
848
|
+
TEST(Intersection, EchoInADisabledStatementStillFires) {
|
|
849
|
+
// echo() runs during resolve, so its side effect happens whatever the
|
|
850
|
+
// geometry does. The result is the cube(2): neither the disabled
|
|
851
|
+
// statement nor the echo statement is an operand.
|
|
853
852
|
std::string captured;
|
|
854
853
|
Evaluated e = evalSrc("intersection() { *cube(10); echo(\"fired\"); cube(2); }", [&](const std::string& msg) { captured = msg; });
|
|
855
854
|
EXPECT_EQ(captured, "ECHO: \"fired\"");
|
|
856
|
-
|
|
855
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
856
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
|
|
857
857
|
}
|
|
858
858
|
|
|
859
859
|
TEST(ListComprehension, IfClauseWithNestedListLiteralBody) {
|
|
@@ -91,7 +91,7 @@ TEST(ExportStl, NoGeometryThrows) {
|
|
|
91
91
|
TEST(ToRenderableBodies, ThinExtrudesABareTopLevel2dShapeSoItCanExportAsStl) {
|
|
92
92
|
// A bare `circle();` (no `body`, only `section`) would make writeStl
|
|
93
93
|
// throw "No geometry to export" -- toRenderableBodies() converts it
|
|
94
|
-
// into a
|
|
94
|
+
// into a 1-unit-tall Manifold first, mirroring the reference
|
|
95
95
|
// CLI's own to_renderable_bodies() call right before export. Without
|
|
96
96
|
// this step, no top-level 2D-only script could ever export a mesh.
|
|
97
97
|
std::vector<ColoredBody> bodies = evalToBodies("circle(2, $fn=32);");
|
|
@@ -104,7 +104,9 @@ TEST(ToRenderableBodies, ThinExtrudesABareTopLevel2dShapeSoItCanExportAsStl) {
|
|
|
104
104
|
ASSERT_TRUE(renderable[0].body.has_value());
|
|
105
105
|
EXPECT_TRUE(renderable[0].flatPreview);
|
|
106
106
|
manifold::Box bbox = renderable[0].body->BoundingBox();
|
|
107
|
-
|
|
107
|
+
// 1 unit, matching what the reference extrudes a 2D preview to --
|
|
108
|
+
// measured against OpenSCAD at three camera tilts.
|
|
109
|
+
EXPECT_NEAR(bbox.max.z - bbox.min.z, 1.0, 1e-9);
|
|
108
110
|
|
|
109
111
|
const std::string path = tempPath("flat_preview.stl").string();
|
|
110
112
|
writeStl(path, renderable);
|
|
File without changes
|
{openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/.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
|
|
File without changes
|
{openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.55.2 → openscad_cpp_evaluator-0.55.4}/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
|
|
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
|