openscad-cpp-evaluator 0.55.4__tar.gz → 0.55.5__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.4 → openscad_cpp_evaluator-0.55.5}/CLAUDE.md +25 -8
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/bytecode.hpp +6 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/colored_body.hpp +17 -10
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/transforms.cpp +156 -5
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/bytecode_compiler.cpp +8 -6
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/bytecode_vm.cpp +6 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/colored_body.cpp +4 -4
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/stmt_eval.cpp +10 -2
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_booleans.cpp +103 -12
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_control_flow.cpp +33 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/.gitignore +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/.gitmodules +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/LICENSE +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/README.md +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/uv.lock +0 -0
|
@@ -231,14 +231,31 @@ 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::
|
|
235
|
-
2D, so `down(1) square(10)` had nowhere to put the `-1` and
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
234
|
+
`ColoredBody::sectionXform` rides alongside for the same reason. A `manifold::CrossSection` is
|
|
235
|
+
purely 2D, so `down(1) square(10)` had nowhere to put the `-1` and `rotate([55,0,25]) text("Foo")`
|
|
236
|
+
had nowhere to put the rotation — both were silently dropped, and neither is cosmetic: BOSL2 layers
|
|
237
|
+
2D overlays by pushing one down (isosurface's `contour()` Example 1 puts a blue backdrop below a
|
|
238
|
+
green contour, and the two slabs became exactly coplanar and z-fought), and turns 2D labels to face
|
|
239
|
+
the camera with `rotate($vpr)` (skin's style figure, which came out lying flat and reading as a blob
|
|
240
|
+
once the preview slab became a full unit tall). `generateTransform` accumulates whatever the
|
|
241
|
+
CrossSection cannot hold into that matrix and `toRenderableBodies()` applies it to the extruded
|
|
242
|
+
slab.
|
|
243
|
+
|
|
244
|
+
Two rules keep the ordering honest. A transform the CrossSection *can* hold still goes into it, so
|
|
245
|
+
2D booleans and `offset()` keep operating on real 2D geometry — but only while the carried matrix is
|
|
246
|
+
still identity, since applying an outer transform to the section after an out-of-plane one would
|
|
247
|
+
silently reorder them. A pure `translate` is the one exception: while nothing has yet rotated or
|
|
248
|
+
scaled the section, its x/y goes into the section and only its z rides along, because translations
|
|
249
|
+
commute and that keeps `down(1) square(10)` a real 2D shape. `resize()` is carried by neither — the
|
|
250
|
+
reference passes 2D children through it unchanged.
|
|
251
|
+
|
|
252
|
+
The same "geometry Manifold cannot hold" problem applies to `ColoredBody::rawMesh`, the raw triangles
|
|
253
|
+
of a mesh Manifold rejected (an open surface — a height field, a partial `vnf_vertex_array`). Those
|
|
254
|
+
were left where they were built, so `grid_copies(...) vnf_polyhedron(<open surface>)` stacked every
|
|
255
|
+
copy at the origin and BOSL2's skin() style figure showed one shape where the reference shows seven.
|
|
256
|
+
`transformMatrix3d` (transforms.cpp) gives the affine matrix for a transform and
|
|
257
|
+
`generateTransform` applies it to those vertices too; `resize` returns nullopt there, being a
|
|
258
|
+
function of a bounding box a display-only body does not have.
|
|
242
259
|
|
|
243
260
|
**Font support**: a `FontProvider` abstract interface (`font_provider.hpp`: `resolveFont`/
|
|
244
261
|
`metrics`/`shapeText`/`glyphInkBounds`/`glyphOutline`) with `FreetypeFontProvider` as the built-in
|
|
@@ -15,6 +15,7 @@ class FunctionLiteral;
|
|
|
15
15
|
class ModuleDeclaration;
|
|
16
16
|
class ModularCall;
|
|
17
17
|
class ModularAssert;
|
|
18
|
+
class ModularEcho;
|
|
18
19
|
class Expression;
|
|
19
20
|
} // namespace oscad
|
|
20
21
|
|
|
@@ -868,6 +869,11 @@ struct CompiledChunk {
|
|
|
868
869
|
// unused and misleadingly defaulted.
|
|
869
870
|
struct EchoSite {
|
|
870
871
|
std::vector<std::optional<std::string>> argNames;
|
|
872
|
+
// The ModularEcho statement, when this site came from one -- an
|
|
873
|
+
// `echo(...) cube();` renders its child after echoing, exactly as
|
|
874
|
+
// AssertSite::node does for `assert(...) cube();`. Null for the
|
|
875
|
+
// EXPRESSION form (`echo(...) 1+1`), which has no children.
|
|
876
|
+
const oscad::ModularEcho* node = nullptr;
|
|
871
877
|
};
|
|
872
878
|
|
|
873
879
|
// One Op::CallModule site -- a ModularCall statically resolved (at
|
|
@@ -25,20 +25,27 @@ struct ColoredBody {
|
|
|
25
25
|
std::optional<manifold::CrossSection> section;
|
|
26
26
|
bool flatPreview = false;
|
|
27
27
|
|
|
28
|
-
//
|
|
29
|
-
//
|
|
28
|
+
// What a 2D `section` has been transformed BY that a CrossSection
|
|
29
|
+
// cannot itself hold: a translation along Z, a rotation out of the XY
|
|
30
|
+
// plane, anything with a Z component. Applied when
|
|
31
|
+
// toRenderableBodies() extrudes the section.
|
|
30
32
|
//
|
|
31
33
|
// A manifold::CrossSection is purely 2D, so `down(1) square(10)` had
|
|
32
|
-
// nowhere to put the -1 and
|
|
34
|
+
// nowhere to put the -1 and `rotate([55,0,25]) text("Foo")` had nowhere
|
|
35
|
+
// to put the rotation -- both were silently dropped. Neither is
|
|
33
36
|
// cosmetic: BOSL2 layers 2D overlays by pushing one down (isosurface's
|
|
34
|
-
// contour() Example 1
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
+
// contour() Example 1), and turns 2D labels to face the camera with
|
|
38
|
+
// `rotate($vpr)` (skin's style figure), which came out lying flat and
|
|
39
|
+
// read as a blob once the preview slab became a full unit tall.
|
|
37
40
|
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
41
|
+
// Identity while every transform so far has been 2D-representable --
|
|
42
|
+
// those still go into the CrossSection itself, so 2D booleans and
|
|
43
|
+
// offset() keep working on real 2D geometry. From the first transform
|
|
44
|
+
// that is NOT representable, every later one composes here instead:
|
|
45
|
+
// applying an outer transform to the section after an out-of-plane one
|
|
46
|
+
// would put it in the wrong order.
|
|
47
|
+
manifold::mat3x4 sectionXform{manifold::vec3(1, 0, 0), manifold::vec3(0, 1, 0),
|
|
48
|
+
manifold::vec3(0, 0, 1), manifold::vec3(0, 0, 0)};
|
|
42
49
|
BodyRole role = BodyRole::Normal;
|
|
43
50
|
std::optional<std::vector<std::array<float, 4>>> triColors; // per-triangle RGBA, multi-color CSG merges only
|
|
44
51
|
|
|
@@ -83,6 +83,15 @@ manifold::Manifold applyRotate(manifold::Manifold body, const Value& aArg, const
|
|
|
83
83
|
return body.Transform(axisAngleMatrix(axis, angle * std::numbers::pi / 180.0));
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// `a` applied after `b`, both as Manifold's column-major 3x4 affines.
|
|
87
|
+
manifold::mat3x4 compose3x4(const manifold::mat3x4& a, const manifold::mat3x4& b) {
|
|
88
|
+
manifold::mat3x4 out;
|
|
89
|
+
for (int c = 0; c < 3; ++c)
|
|
90
|
+
out[c] = a[0] * b[c].x + a[1] * b[c].y + a[2] * b[c].z;
|
|
91
|
+
out[3] = a[0] * b[3].x + a[1] * b[3].y + a[2] * b[3].z + a[3];
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
// Converts a user-supplied 4x4/4x3 nested-list matrix (row-major, like
|
|
87
96
|
// every OpenSCAD-facing representation) to Manifold's column-major 3x4
|
|
88
97
|
// transform. Mirrors _to_matrix4x3.
|
|
@@ -117,6 +126,121 @@ manifold::mat2x3 toMat2x3(const Value& m) {
|
|
|
117
126
|
return manifold::mat2x3(col0, col1, col2);
|
|
118
127
|
}
|
|
119
128
|
|
|
129
|
+
// The affine matrix a transform applies, for geometry Manifold cannot hold.
|
|
130
|
+
//
|
|
131
|
+
// A mesh Manifold rejected (an open surface -- a height field, a partial
|
|
132
|
+
// `vnf_vertex_array`) survives only as ColoredBody::rawMesh, raw triangles
|
|
133
|
+
// with no Manifold to transform. Those triangles were left where they were
|
|
134
|
+
// built, so `grid_copies(...) vnf_polyhedron(<open surface>)` stacked every
|
|
135
|
+
// copy at the origin and BOSL2's skin() style figure showed one shape where
|
|
136
|
+
// the reference shows seven.
|
|
137
|
+
//
|
|
138
|
+
// nullopt for `resize`, which is not a fixed map at all: its scale comes
|
|
139
|
+
// from the body's own bounding box, and a display-only body has no Manifold
|
|
140
|
+
// to measure. Verified against Manifold's own operators by
|
|
141
|
+
// TransformMatrix3d tests rather than assumed -- the Euler order especially.
|
|
142
|
+
// True if `m` is a pure translation: nothing has rotated, scaled or
|
|
143
|
+
// mirrored the section, so a further translation commutes with it.
|
|
144
|
+
bool hasIdentityLinearPart(const manifold::mat3x4& m) {
|
|
145
|
+
for (int c = 0; c < 3; ++c) {
|
|
146
|
+
const manifold::vec3 want(c == 0 ? 1.0 : 0.0, c == 1 ? 1.0 : 0.0, c == 2 ? 1.0 : 0.0);
|
|
147
|
+
if (m[c] != want) return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
bool isIdentity3x4(const manifold::mat3x4& m) {
|
|
153
|
+
for (int c = 0; c < 4; ++c) {
|
|
154
|
+
const manifold::vec3 want(c == 0 ? 1.0 : 0.0, c == 1 ? 1.0 : 0.0, c == 2 ? 1.0 : 0.0);
|
|
155
|
+
if (m[c] != want) return false;
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// True if `m` maps the XY plane onto itself, so a CrossSection can hold it:
|
|
161
|
+
// nothing leaves the plane (no Z from x or y, no Z offset) and Z maps to Z.
|
|
162
|
+
bool preservesXYPlane(const manifold::mat3x4& m) {
|
|
163
|
+
return m[0].z == 0.0 && m[1].z == 0.0 && m[3].z == 0.0 &&
|
|
164
|
+
m[2].x == 0.0 && m[2].y == 0.0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Applies `m` to a raw mesh's vertex POSITIONS in place. Any further
|
|
168
|
+
// per-vertex properties (normals and the like) are left alone: nothing
|
|
169
|
+
// reads them off a display-only body, which is drawn from its triangles.
|
|
170
|
+
void transformMeshInPlace(manifold::MeshGL& mesh, const manifold::mat3x4& m) {
|
|
171
|
+
const uint32_t stride = mesh.numProp;
|
|
172
|
+
if (stride < 3) return;
|
|
173
|
+
for (size_t i = 0; i + 2 < mesh.vertProperties.size(); i += stride) {
|
|
174
|
+
const double x = mesh.vertProperties[i];
|
|
175
|
+
const double y = mesh.vertProperties[i + 1];
|
|
176
|
+
const double z = mesh.vertProperties[i + 2];
|
|
177
|
+
const manifold::vec3 p = m[0] * x + m[1] * y + m[2] * z + m[3];
|
|
178
|
+
mesh.vertProperties[i] = static_cast<float>(p.x);
|
|
179
|
+
mesh.vertProperties[i + 1] = static_cast<float>(p.y);
|
|
180
|
+
mesh.vertProperties[i + 2] = static_cast<float>(p.z);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
std::optional<manifold::mat3x4> transformMatrix3d(const std::string& name, const CallArgs& args) {
|
|
185
|
+
const manifold::mat3x4 ident(manifold::vec3(1, 0, 0), manifold::vec3(0, 1, 0),
|
|
186
|
+
manifold::vec3(0, 0, 1), manifold::vec3(0, 0, 0));
|
|
187
|
+
if (name == "translate") {
|
|
188
|
+
manifold::mat3x4 m = ident;
|
|
189
|
+
m[3] = toVec3(getArg(args, 0, "v", Value{}));
|
|
190
|
+
return m;
|
|
191
|
+
}
|
|
192
|
+
if (name == "rotate") {
|
|
193
|
+
const Value aArg = getArg(args, 0, "a", Value{0.0});
|
|
194
|
+
const Value vArg = getArg(args, 1, "v", Value{});
|
|
195
|
+
if (std::holds_alternative<ListPtr>(aArg)) {
|
|
196
|
+
const manifold::vec3 a = toVec3(aArg);
|
|
197
|
+
const double d2r = std::numbers::pi / 180.0;
|
|
198
|
+
// X, then Y, then Z -- the order Manifold::Rotate uses, which
|
|
199
|
+
// applyTransform3d hands the same angles to.
|
|
200
|
+
const manifold::mat3x4 rx = axisAngleMatrix(manifold::vec3(1, 0, 0), a.x * d2r);
|
|
201
|
+
const manifold::mat3x4 ry = axisAngleMatrix(manifold::vec3(0, 1, 0), a.y * d2r);
|
|
202
|
+
const manifold::mat3x4 rz = axisAngleMatrix(manifold::vec3(0, 0, 1), a.z * d2r);
|
|
203
|
+
return compose3x4(rz, compose3x4(ry, rx));
|
|
204
|
+
}
|
|
205
|
+
const double angle = toDoubleLenient(aArg);
|
|
206
|
+
const manifold::vec3 axis =
|
|
207
|
+
std::holds_alternative<std::monostate>(vArg) ? manifold::vec3(0, 0, 1) : toVec3(vArg);
|
|
208
|
+
return axisAngleMatrix(axis, angle * std::numbers::pi / 180.0);
|
|
209
|
+
}
|
|
210
|
+
if (name == "scale") {
|
|
211
|
+
Value v = getArg(args, 0, "v", Value{1.0});
|
|
212
|
+
manifold::vec3 sv = std::get_if<double>(&v)
|
|
213
|
+
? manifold::vec3(*std::get_if<double>(&v), *std::get_if<double>(&v),
|
|
214
|
+
*std::get_if<double>(&v))
|
|
215
|
+
: toVec3(v, 1.0, 1.0, 1.0);
|
|
216
|
+
manifold::mat3x4 m = ident;
|
|
217
|
+
m[0] = manifold::vec3(sv.x, 0, 0);
|
|
218
|
+
m[1] = manifold::vec3(0, sv.y, 0);
|
|
219
|
+
m[2] = manifold::vec3(0, 0, sv.z);
|
|
220
|
+
return m;
|
|
221
|
+
}
|
|
222
|
+
if (name == "mirror") {
|
|
223
|
+
manifold::vec3 n = toVec3(getArg(args, 0, "v", Value{}), 1.0, 0.0, 0.0);
|
|
224
|
+
const double len2 = n.x * n.x + n.y * n.y + n.z * n.z;
|
|
225
|
+
if (len2 <= 0.0) return ident;
|
|
226
|
+
manifold::mat3x4 m = ident;
|
|
227
|
+
// I - 2 n n^T / |n|^2, written column by column.
|
|
228
|
+
for (int c = 0; c < 3; ++c) {
|
|
229
|
+
const double nc = c == 0 ? n.x : (c == 1 ? n.y : n.z);
|
|
230
|
+
m[c] = manifold::vec3((c == 0 ? 1.0 : 0.0) - 2.0 * n.x * nc / len2,
|
|
231
|
+
(c == 1 ? 1.0 : 0.0) - 2.0 * n.y * nc / len2,
|
|
232
|
+
(c == 2 ? 1.0 : 0.0) - 2.0 * n.z * nc / len2);
|
|
233
|
+
}
|
|
234
|
+
return m;
|
|
235
|
+
}
|
|
236
|
+
if (name == "multmatrix") {
|
|
237
|
+
Value m = getArg(args, 0, "m", Value{});
|
|
238
|
+
if (std::holds_alternative<std::monostate>(m)) return ident;
|
|
239
|
+
return toMat3x4(m);
|
|
240
|
+
}
|
|
241
|
+
return std::nullopt;
|
|
242
|
+
}
|
|
243
|
+
|
|
120
244
|
manifold::Manifold applyTransform3d(const std::string& name, const CallArgs& args, manifold::Manifold body) {
|
|
121
245
|
if (name == "translate") {
|
|
122
246
|
return body.Translate(toVec3(getArg(args, 0, "v", Value{})));
|
|
@@ -233,13 +357,40 @@ std::vector<ColoredBody> generateTransform(Evaluator&, const CSGParams& params,
|
|
|
233
357
|
std::vector<ColoredBody> result;
|
|
234
358
|
for (ColoredBody b : flattenCsgTree(children)) {
|
|
235
359
|
if (b.section) {
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
360
|
+
// A 2D-representable transform goes into the CrossSection, so
|
|
361
|
+
// 2D booleans and offset() keep operating on real 2D geometry.
|
|
362
|
+
// Anything else -- a Z translation, a rotation out of the XY
|
|
363
|
+
// plane -- has nowhere to go there and rides along on the body
|
|
364
|
+
// until the section is extruded. Once one of those has been
|
|
365
|
+
// seen, every LATER (outer) transform must ride along too, or
|
|
366
|
+
// it would be applied in the wrong order. See
|
|
367
|
+
// ColoredBody::sectionXform.
|
|
368
|
+
const std::optional<manifold::mat3x4> m = transformMatrix3d(name, args);
|
|
369
|
+
if (isIdentity3x4(b.sectionXform) && (!m || preservesXYPlane(*m))) {
|
|
370
|
+
b.section = applyTransform2d(name, args, std::move(*b.section));
|
|
371
|
+
} else if (name == "translate" && hasIdentityLinearPart(b.sectionXform)) {
|
|
372
|
+
// A translate SPLITS while nothing has rotated or scaled the
|
|
373
|
+
// section yet: x/y into the CrossSection, z into the carried
|
|
374
|
+
// transform. Translations commute, so the order is safe --
|
|
375
|
+
// and keeping x/y in the section is what lets a later 2D
|
|
376
|
+
// boolean or offset() still see real 2D geometry after a
|
|
377
|
+
// `down(1) square(10)`.
|
|
378
|
+
b.section = applyTransform2d(name, args, std::move(*b.section));
|
|
379
|
+
b.sectionXform[3].z += toVec3(getArg(args, 0, "v", Value{})).z;
|
|
380
|
+
} else if (m) {
|
|
381
|
+
b.sectionXform = compose3x4(*m, b.sectionXform);
|
|
382
|
+
}
|
|
383
|
+
// No `m` and already carrying a transform: only resize(), which
|
|
384
|
+
// the reference passes 2D children through unchanged anyway.
|
|
241
385
|
} else if (b.body) {
|
|
242
386
|
b.body = applyTransform3d(name, args, std::move(*b.body));
|
|
387
|
+
// A display-only body's real geometry is its raw triangles --
|
|
388
|
+
// the Manifold above is empty and moving it moves nothing. See
|
|
389
|
+
// transformMatrix3d.
|
|
390
|
+
if (b.rawMesh) {
|
|
391
|
+
if (std::optional<manifold::mat3x4> m = transformMatrix3d(name, args))
|
|
392
|
+
transformMeshInPlace(*b.rawMesh, *m);
|
|
393
|
+
}
|
|
243
394
|
}
|
|
244
395
|
result.push_back(std::move(b));
|
|
245
396
|
}
|
|
@@ -1501,15 +1501,17 @@ public:
|
|
|
1501
1501
|
// form's own compile case (AssertOp's sibling, above in
|
|
1502
1502
|
// compileExpr) -- already statement-shaped (no value
|
|
1503
1503
|
// pushed, straight fall-through), so nothing new is needed
|
|
1504
|
-
// there. `.children`
|
|
1505
|
-
//
|
|
1506
|
-
//
|
|
1507
|
-
//
|
|
1508
|
-
//
|
|
1509
|
-
//
|
|
1504
|
+
// there. `.children` IS read: `echo("x") cube();` renders the
|
|
1505
|
+
// cube in the reference, and the grammar does produce those
|
|
1506
|
+
// children. They used to be dropped on the assumption that it
|
|
1507
|
+
// never did, which silently lost the geometry -- BOSL2's
|
|
1508
|
+
// debug_region() draws its whole region through
|
|
1509
|
+
// `for(...) echo(...) linear_extrude(...) region(...)` and came
|
|
1510
|
+
// out as labels with nothing under them.
|
|
1510
1511
|
auto& n = static_cast<const oscad::ModularEcho&>(stmt);
|
|
1511
1512
|
out.push_back({Op::CheckDebugStatement, internNativeStatement(&stmt), 0, nullptr});
|
|
1512
1513
|
CompiledChunk::EchoSite site;
|
|
1514
|
+
site.node = &n; // statement form: it can have children
|
|
1513
1515
|
CompileScope exprScope;
|
|
1514
1516
|
for (const auto& argPtr : n.arguments) {
|
|
1515
1517
|
if (argPtr->kind() == NodeKind::NamedArgument) {
|
|
@@ -981,6 +981,12 @@ Value driveVm(Evaluator& ev, size_t floor) {
|
|
|
981
981
|
f.stack.pop_back();
|
|
982
982
|
}
|
|
983
983
|
ev.emitEcho(pairs);
|
|
984
|
+
// The STATEMENT form can carry children and the
|
|
985
|
+
// reference renders them; same tail as
|
|
986
|
+
// Op::AssertStatement below. Null node = the expression
|
|
987
|
+
// form (`echo(...) 1+1`), which has none.
|
|
988
|
+
if (site.node && !site.node->children.empty())
|
|
989
|
+
ev.evalChildren(site.node->children, ctx);
|
|
984
990
|
++f.pc;
|
|
985
991
|
break;
|
|
986
992
|
}
|
|
@@ -37,10 +37,10 @@ std::vector<ColoredBody> toRenderableBodies(const std::vector<ColoredBody>& bodi
|
|
|
37
37
|
if (!cb.body && cb.section) {
|
|
38
38
|
ColoredBody flat;
|
|
39
39
|
flat.body = manifold::Manifold::Extrude(cb.section->ToPolygons(), kTopLevel2dHeight);
|
|
40
|
-
// Put it back where
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
// Put it back where the transforms a CrossSection could not
|
|
41
|
+
// hold would have placed it -- a Z offset, a rotation out of
|
|
42
|
+
// the plane. See ColoredBody::sectionXform.
|
|
43
|
+
flat.body = flat.body->Transform(cb.sectionXform);
|
|
44
44
|
flat.color = cb.color;
|
|
45
45
|
flat.flatPreview = true;
|
|
46
46
|
flat.role = cb.role;
|
|
@@ -241,9 +241,17 @@ void Evaluator::evalStatement(const oscad::ASTNode& node, EvalContext& ctx) {
|
|
|
241
241
|
case oscad::NodeKind::ModularLet:
|
|
242
242
|
evalLetBlock(static_cast<const oscad::ModularLet&>(node), ctx);
|
|
243
243
|
return;
|
|
244
|
-
case oscad::NodeKind::ModularEcho:
|
|
245
|
-
|
|
244
|
+
case oscad::NodeKind::ModularEcho: {
|
|
245
|
+
// `echo("x") cube();` echoes AND renders the cube, the way the
|
|
246
|
+
// reference does and the way ModularAssert already did here.
|
|
247
|
+
// Dropping the children silently lost geometry: BOSL2's
|
|
248
|
+
// debug_region() draws its whole region through
|
|
249
|
+
// `for(...) echo(...) linear_extrude(...) region(...)`.
|
|
250
|
+
const auto& e = static_cast<const oscad::ModularEcho&>(node);
|
|
251
|
+
doEcho(e.arguments, ctx);
|
|
252
|
+
if (!e.children.empty()) evalChildren(e.children, ctx);
|
|
246
253
|
return;
|
|
254
|
+
}
|
|
247
255
|
case oscad::NodeKind::ModularAssert:
|
|
248
256
|
evalAssertStatement(static_cast<const oscad::ModularAssert&>(node), ctx);
|
|
249
257
|
return;
|
|
@@ -731,7 +731,6 @@ TEST(MixedDimensions, ATranslatedTwoDeeShapeKeepsItsZ) {
|
|
|
731
731
|
Evaluated e = evalSrc("translate([0,0,-1]) square(10, center=true);");
|
|
732
732
|
ASSERT_EQ(e.bodies.size(), 1u);
|
|
733
733
|
ASSERT_TRUE(e.bodies[0].section.has_value());
|
|
734
|
-
EXPECT_DOUBLE_EQ(e.bodies[0].sectionZ, -1.0);
|
|
735
734
|
|
|
736
735
|
const std::vector<ColoredBody> renderable = toRenderableBodies(e.bodies);
|
|
737
736
|
ASSERT_EQ(renderable.size(), 1u);
|
|
@@ -740,23 +739,115 @@ TEST(MixedDimensions, ATranslatedTwoDeeShapeKeepsItsZ) {
|
|
|
740
739
|
EXPECT_NEAR(box.min.z, -1.0, 1e-9) << "the extruded slab sits where it was moved to";
|
|
741
740
|
}
|
|
742
741
|
|
|
743
|
-
TEST(MixedDimensions,
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
742
|
+
TEST(MixedDimensions, ARotatedTwoDeeShapeLeavesTheXYPlane) {
|
|
743
|
+
// `rotate([90,0,0]) square(10)` stands the square up. A CrossSection
|
|
744
|
+
// cannot hold that either, and dropping it left BOSL2's `rotate($vpr)`
|
|
745
|
+
// labels lying flat -- which read as blobs once the preview slab became
|
|
746
|
+
// a full unit tall rather than a 1e-3 sliver.
|
|
747
|
+
Evaluated e = evalSrc("rotate([90,0,0]) square(10);");
|
|
748
|
+
const std::vector<ColoredBody> renderable = toRenderableBodies(e.bodies);
|
|
749
|
+
ASSERT_EQ(renderable.size(), 1u);
|
|
750
|
+
const manifold::Box box = renderable[0].body->BoundingBox();
|
|
751
|
+
// Standing up: 10 tall in Z, and flat (the slab thickness) in Y.
|
|
752
|
+
EXPECT_NEAR(box.max.z - box.min.z, 10.0, 1e-6);
|
|
753
|
+
EXPECT_NEAR(box.max.y - box.min.y, 1.0, 1e-6) << "the 1-unit slab is now the Y extent";
|
|
754
|
+
EXPECT_NEAR(box.max.x - box.min.x, 10.0, 1e-6);
|
|
755
|
+
}
|
|
747
756
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
757
|
+
TEST(MixedDimensions, TwoDeeTransformsComposeInSourceOrder) {
|
|
758
|
+
// The outer translate must act AFTER the rotation, not before it: with
|
|
759
|
+
// the rotation carried separately, applying a later transform to the
|
|
760
|
+
// CrossSection would silently reorder them.
|
|
761
|
+
Evaluated e = evalSrc("translate([0,0,7]) rotate([90,0,0]) square(10);");
|
|
762
|
+
const std::vector<ColoredBody> renderable = toRenderableBodies(e.bodies);
|
|
763
|
+
ASSERT_EQ(renderable.size(), 1u);
|
|
764
|
+
const manifold::Box box = renderable[0].body->BoundingBox();
|
|
765
|
+
EXPECT_NEAR(box.min.z, 7.0, 1e-6) << "lifted after standing up";
|
|
766
|
+
EXPECT_NEAR(box.max.z, 17.0, 1e-6);
|
|
767
|
+
}
|
|
752
768
|
|
|
753
|
-
|
|
769
|
+
TEST(MixedDimensions, PlanarTransformsStillGoIntoTheCrossSection) {
|
|
770
|
+
// Anything the CrossSection CAN hold still goes there, so 2D booleans
|
|
771
|
+
// and offset() keep working on real 2D geometry.
|
|
754
772
|
Evaluated moved = evalSrc("translate([4,5,6]) square(10);");
|
|
755
773
|
ASSERT_EQ(moved.bodies.size(), 1u);
|
|
756
|
-
|
|
774
|
+
ASSERT_TRUE(moved.bodies[0].section.has_value());
|
|
757
775
|
const manifold::Rect r = moved.bodies[0].section->Bounds();
|
|
758
|
-
EXPECT_NEAR(r.min.x, 4.0, 1e-9);
|
|
776
|
+
EXPECT_NEAR(r.min.x, 4.0, 1e-9) << "x/y went into the section itself";
|
|
759
777
|
EXPECT_NEAR(r.min.y, 5.0, 1e-9);
|
|
778
|
+
|
|
779
|
+
// ...and the z rode along, so the extruded slab still lands at 6.
|
|
780
|
+
const std::vector<ColoredBody> renderable = toRenderableBodies(moved.bodies);
|
|
781
|
+
EXPECT_NEAR(renderable[0].body->BoundingBox().min.z, 6.0, 1e-9);
|
|
782
|
+
|
|
783
|
+
// Two stacked z offsets accumulate rather than the last one winning.
|
|
784
|
+
Evaluated stacked = evalSrc("translate([0,0,2]) translate([0,0,3]) square(10);");
|
|
785
|
+
const std::vector<ColoredBody> r2 = toRenderableBodies(stacked.bodies);
|
|
786
|
+
EXPECT_NEAR(r2[0].body->BoundingBox().min.z, 5.0, 1e-9);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// -- transforms on a display-only (open surface) body ---------------------
|
|
790
|
+
|
|
791
|
+
namespace {
|
|
792
|
+
// A cube with one face left off: Manifold rejects it, so it survives only
|
|
793
|
+
// as ColoredBody::rawMesh -- the shape that ignored every transform.
|
|
794
|
+
constexpr const char* kOpenBox =
|
|
795
|
+
"polyhedron(points=[[0,0,0],[10,0,0],[10,10,0],[0,10,0],"
|
|
796
|
+
" [0,0,10],[10,0,10],[10,10,10],[0,10,10]],"
|
|
797
|
+
" faces=[[0,1,2,3],[4,5,1,0],[5,6,2,1],[6,7,3,2],[7,4,0,3]]);";
|
|
798
|
+
|
|
799
|
+
std::array<double, 6> rawBounds(const Evaluated& e) {
|
|
800
|
+
std::array<double, 6> b{1e30, 1e30, 1e30, -1e30, -1e30, -1e30};
|
|
801
|
+
for (const ColoredBody& cb : e.bodies) {
|
|
802
|
+
if (!cb.rawMesh) continue;
|
|
803
|
+
const auto& mesh = *cb.rawMesh;
|
|
804
|
+
for (size_t i = 0; i + 2 < mesh.vertProperties.size(); i += mesh.numProp) {
|
|
805
|
+
for (int k = 0; k < 3; ++k) {
|
|
806
|
+
b[static_cast<size_t>(k)] = std::min(b[static_cast<size_t>(k)],
|
|
807
|
+
static_cast<double>(mesh.vertProperties[i + static_cast<size_t>(k)]));
|
|
808
|
+
b[static_cast<size_t>(k + 3)] = std::max(b[static_cast<size_t>(k + 3)],
|
|
809
|
+
static_cast<double>(mesh.vertProperties[i + static_cast<size_t>(k)]));
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return b;
|
|
814
|
+
}
|
|
815
|
+
} // namespace
|
|
816
|
+
|
|
817
|
+
TEST(DisplayOnlyTransforms, RawTrianglesFollowTheSameTransformAsASolid) {
|
|
818
|
+
// The open box and a closed cube occupy the same 10-cube, so after the
|
|
819
|
+
// SAME transform their bounding boxes must still agree. They did not:
|
|
820
|
+
// the raw triangles were left where they were built, so every copy of
|
|
821
|
+
// an open surface stacked at the origin -- BOSL2's skin() style figure
|
|
822
|
+
// showed one shape where the reference shows seven.
|
|
823
|
+
const char* xforms[] = {
|
|
824
|
+
"translate([5,-3,2])",
|
|
825
|
+
"rotate([30,40,50])",
|
|
826
|
+
"scale([2,0.5,1.5])",
|
|
827
|
+
"mirror([1,1,0])",
|
|
828
|
+
"multmatrix([[1,0.2,0,4],[0,1,0,5],[0,0,1,6]])",
|
|
829
|
+
"rotate(35, v=[1,2,3])",
|
|
830
|
+
};
|
|
831
|
+
for (const char* x : xforms) {
|
|
832
|
+
Evaluated open = evalSrc(std::string(x) + " " + kOpenBox);
|
|
833
|
+
Evaluated solid = evalSrc(std::string(x) + " cube(10);");
|
|
834
|
+
ASSERT_EQ(solid.bodies.size(), 1u) << x;
|
|
835
|
+
const manifold::Box want = solid.bodies[0].body->BoundingBox();
|
|
836
|
+
const std::array<double, 6> got = rawBounds(open);
|
|
837
|
+
EXPECT_NEAR(got[0], want.min.x, 1e-4) << x;
|
|
838
|
+
EXPECT_NEAR(got[1], want.min.y, 1e-4) << x;
|
|
839
|
+
EXPECT_NEAR(got[2], want.min.z, 1e-4) << x;
|
|
840
|
+
EXPECT_NEAR(got[3], want.max.x, 1e-4) << x;
|
|
841
|
+
EXPECT_NEAR(got[4], want.max.y, 1e-4) << x;
|
|
842
|
+
EXPECT_NEAR(got[5], want.max.z, 1e-4) << x;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
TEST(DisplayOnlyTransforms, EachCopyLandsSomewhereDifferent) {
|
|
847
|
+
Evaluated e = evalSrc(std::string("for (i = [0:2]) translate([20*i, 0, 0]) ") + kOpenBox);
|
|
848
|
+
const std::array<double, 6> b = rawBounds(e);
|
|
849
|
+
EXPECT_NEAR(b[0], 0.0, 1e-6);
|
|
850
|
+
EXPECT_NEAR(b[3], 50.0, 1e-6) << "three copies 20 apart span 0..50, not one box";
|
|
760
851
|
}
|
|
761
852
|
|
|
762
853
|
TEST(MixedDimensions, UniformChildrenAreUntouched) {
|
|
@@ -845,6 +845,38 @@ TEST(ExprEvalFunctionCall, CallingANonFunctionVariableWarnsAndIsUndef) {
|
|
|
845
845
|
EXPECT_NE(warnings.back().find("Ignoring unknown function 'x'"), std::string::npos);
|
|
846
846
|
}
|
|
847
847
|
|
|
848
|
+
TEST(EchoStatement, RendersItsChildren) {
|
|
849
|
+
// `echo("x") cube();` -- echo used as a statement PREFIX. The reference
|
|
850
|
+
// echoes and then renders the child; we echoed and dropped it, on the
|
|
851
|
+
// stated assumption that the grammar never produced children here. It
|
|
852
|
+
// does. BOSL2's debug_region() draws its whole region through
|
|
853
|
+
// `for(...) echo(...) linear_extrude(...) region(...)` and came out as
|
|
854
|
+
// labels with nothing under them.
|
|
855
|
+
const char* cases[] = {
|
|
856
|
+
"echo(\"hi\") cube(10);",
|
|
857
|
+
"echo(\"hi\") { cube(10); }",
|
|
858
|
+
"echo(\"a\") echo(\"b\") cube(10);",
|
|
859
|
+
"for (i = [0:1]) echo(\"hi\") translate([i*20,0,0]) cube(10);",
|
|
860
|
+
"union() { echo(\"hi\") cube(10); }",
|
|
861
|
+
};
|
|
862
|
+
for (const char* src : cases) {
|
|
863
|
+
Evaluated e = evalSrc(src);
|
|
864
|
+
const bool anyVolume = std::any_of(
|
|
865
|
+
e.bodies.begin(), e.bodies.end(),
|
|
866
|
+
[](const ColoredBody& b) { return b.body && !b.body->IsEmpty(); });
|
|
867
|
+
EXPECT_TRUE(anyVolume) << src;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
TEST(EchoStatement, StillEchoesAndKeepsArgumentsSeparateFromChildren) {
|
|
872
|
+
std::string captured;
|
|
873
|
+
Evaluated e = evalSrc("echo(\"fired\") cube(2);",
|
|
874
|
+
[&](const std::string& msg) { captured = msg; });
|
|
875
|
+
EXPECT_EQ(captured, "ECHO: \"fired\"");
|
|
876
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
877
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-6);
|
|
878
|
+
}
|
|
879
|
+
|
|
848
880
|
TEST(Intersection, EchoInADisabledStatementStillFires) {
|
|
849
881
|
// echo() runs during resolve, so its side effect happens whatever the
|
|
850
882
|
// geometry does. The result is the cube(2): neither the disabled
|
|
@@ -1761,3 +1793,4 @@ TEST(RangeDirection, EveryRangeBuildingConstructWarns) {
|
|
|
1761
1793
|
<< "returned from a function";
|
|
1762
1794
|
}
|
|
1763
1795
|
|
|
1796
|
+
|
|
File without changes
|
{openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/.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.4 → openscad_cpp_evaluator-0.55.5}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-0.55.4 → openscad_cpp_evaluator-0.55.5}/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
|