openscad-cpp-evaluator 1.47.0__tar.gz → 1.48.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/CLAUDE.md +6 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/function_builtins.cpp +1 -1
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/topology.cpp +100 -45
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_booleans.cpp +70 -2
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/uv.lock +1 -1
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/README.md +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/cmake/patch_manifold.cmake +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/LICENSE +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/mesh_import.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/roof.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/import/mesh_import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/import/scene_import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_extrude_roof.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_import_export.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_openscad_parity.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_undef_args.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/tools/cli/main.cpp +0 -0
|
@@ -606,6 +606,12 @@ grep for `ponytail:`.
|
|
|
606
606
|
field squashed to unit spacing and `Scale`s the result back -- exact, since with tolerance -1 a
|
|
607
607
|
vertex is a linear interpolation along a lattice edge, which commutes with an axis scale. A plain
|
|
608
608
|
number takes the old path unchanged. `supported_feature("levelset")` is **2** from this change.
|
|
609
|
+
**A field array needs `bounds` OR `edge`**: given only `edge` (number or vector), the samples sit
|
|
610
|
+
`edge` apart **centred on the origin**, as BOSL2's `isosurface()` places an array given
|
|
611
|
+
`voxel_size`, and the array's depth (`field[i][j]` vs `field[i][j][k]`) decides 2D or 3D
|
|
612
|
+
(`boundsFromEdge`, #749 on BelfrySCAD). Both given: `edge` re-samples the field inside `bounds`
|
|
613
|
+
(trilinear in 3D, bilinear in 2D -- 2D used to ignore `edge` here) unless it equals the grid's own spacing. A function field still needs `bounds`.
|
|
614
|
+
`supported_feature("levelset")` is **3** from this change.
|
|
609
615
|
**The field is a grid OR a `function(x,y,z)`, and the two trade off against each other** —
|
|
610
616
|
neither is simply better:
|
|
611
617
|
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/src/builtins/function_builtins.cpp
RENAMED
|
@@ -987,7 +987,7 @@ const std::unordered_map<std::string, double>& featureLevels() {
|
|
|
987
987
|
static const std::unordered_map<std::string, double> levels = {
|
|
988
988
|
{"render-expr", 1.0}, // render() in expression position
|
|
989
989
|
{"linear-solve", 1.0}, // linear_solve(A, b) -> {x, det, singular}
|
|
990
|
-
{"levelset",
|
|
990
|
+
{"levelset", 3.0}, // levelset(field, bounds, isovalue); 2: edge may be a vector; 3: edge alone places a field array
|
|
991
991
|
{"polyhedron-vnf", 1.0}, // polyhedron(vnf) / polyhedron(object)
|
|
992
992
|
{"separate-children", 1.0}, // children(..., separate=true)
|
|
993
993
|
{"minkowski-diff", 1.0}, // minkowski_difference()
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <manifold/polygon.h>
|
|
8
8
|
|
|
9
9
|
#include <algorithm>
|
|
10
|
+
#include <utility>
|
|
10
11
|
|
|
11
12
|
namespace oscadeval {
|
|
12
13
|
|
|
@@ -689,6 +690,44 @@ std::optional<double> fieldSample(const Value& item) {
|
|
|
689
690
|
return std::clamp(*d, -kHuge, kHuge);
|
|
690
691
|
}
|
|
691
692
|
|
|
693
|
+
// bounds for a field ARRAY given edge= and no bounds (#749 on BelfrySCAD):
|
|
694
|
+
// the samples edge apart, centred on the origin, as BOSL2's isosurface()
|
|
695
|
+
// places an array given voxel_size. The array's depth (field[i][j] or
|
|
696
|
+
// field[i][j][k]) says 2D or 3D; the sizes come from its first row, and
|
|
697
|
+
// readField/readPlane check the rest later. nullopt when edge is missing
|
|
698
|
+
// or does not fit, leaving the caller's "bounds must be ..." warning.
|
|
699
|
+
std::optional<std::pair<std::vector<double>, std::vector<double>>>
|
|
700
|
+
boundsFromEdge(const Value& field, const Value& edge) {
|
|
701
|
+
std::vector<size_t> dims;
|
|
702
|
+
for (const Value* cur = &field; dims.size() < 3;) {
|
|
703
|
+
const ListPtr* l = std::get_if<ListPtr>(cur);
|
|
704
|
+
if (!l || !*l || (*l)->items.empty()) break;
|
|
705
|
+
dims.push_back((*l)->items.size());
|
|
706
|
+
cur = &(*l)->items[0];
|
|
707
|
+
}
|
|
708
|
+
if (dims.size() < 2) return std::nullopt;
|
|
709
|
+
std::vector<double> step;
|
|
710
|
+
if (const double* e = std::get_if<double>(&edge)) {
|
|
711
|
+
step.assign(dims.size(), *e);
|
|
712
|
+
} else if (const ListPtr* l = std::get_if<ListPtr>(&edge); l && *l && (*l)->items.size() == dims.size()) {
|
|
713
|
+
for (const Value& item : (*l)->items) {
|
|
714
|
+
const double* d = std::get_if<double>(&item);
|
|
715
|
+
if (!d) return std::nullopt;
|
|
716
|
+
step.push_back(*d);
|
|
717
|
+
}
|
|
718
|
+
} else {
|
|
719
|
+
return std::nullopt;
|
|
720
|
+
}
|
|
721
|
+
std::vector<double> lo, hi;
|
|
722
|
+
for (size_t a = 0; a < dims.size(); ++a) {
|
|
723
|
+
if (!std::isfinite(step[a]) || step[a] <= 0.0 || dims[a] < 2) return std::nullopt;
|
|
724
|
+
const double half = 0.5 * step[a] * static_cast<double>(dims[a] - 1);
|
|
725
|
+
lo.push_back(-half);
|
|
726
|
+
hi.push_back(half);
|
|
727
|
+
}
|
|
728
|
+
return std::make_pair(lo, hi);
|
|
729
|
+
}
|
|
730
|
+
|
|
692
731
|
struct ScalarField {
|
|
693
732
|
std::vector<double> v; // flat, x fastest
|
|
694
733
|
size_t nx = 0, ny = 0, nz = 0;
|
|
@@ -1108,12 +1147,20 @@ std::vector<ColoredBody> generateLevelSet(Evaluator& ev, const CSGParams& params
|
|
|
1108
1147
|
// matches how the caller already has to think about the box.
|
|
1109
1148
|
const ListPtr* bb = std::get_if<ListPtr>(¶ms.at("bounds"));
|
|
1110
1149
|
std::optional<std::vector<double>> bLo, bHi;
|
|
1150
|
+
const bool noBounds = std::holds_alternative<std::monostate>(params.at("bounds"));
|
|
1111
1151
|
if (bb && *bb && (*bb)->items.size() == 2) {
|
|
1112
1152
|
bLo = numbersOrInf((*bb)->items[0]);
|
|
1113
1153
|
bHi = numbersOrInf((*bb)->items[1]);
|
|
1154
|
+
} else if (noBounds && !fieldFn) {
|
|
1155
|
+
if (const auto inferred = boundsFromEdge(fieldArg, params.at("edge"))) {
|
|
1156
|
+
bLo = inferred->first;
|
|
1157
|
+
bHi = inferred->second;
|
|
1158
|
+
}
|
|
1114
1159
|
}
|
|
1115
1160
|
if (!bLo || !bHi || bLo->size() != bHi->size() || (bLo->size() != 2 && bLo->size() != 3)) {
|
|
1116
|
-
ev.warn(
|
|
1161
|
+
ev.warn(noBounds && !fieldFn
|
|
1162
|
+
? "levelset(): a field array needs bounds=, or edge= (its sample spacing) to place it"
|
|
1163
|
+
: "levelset(): bounds must be [[x0,y0],[x1,y1]] or [[x0,y0,z0],[x1,y1,z1]]",
|
|
1117
1164
|
&node.position());
|
|
1118
1165
|
return {};
|
|
1119
1166
|
}
|
|
@@ -1211,74 +1258,82 @@ std::vector<ColoredBody> generateLevelSet(Evaluator& ev, const CSGParams& params
|
|
|
1211
1258
|
|
|
1212
1259
|
// ---- 2D: sample onto a padded grid, contour it, hand to CrossSection.
|
|
1213
1260
|
if (is2d) {
|
|
1214
|
-
size_t nx = 0, ny = 0;
|
|
1215
|
-
double sx = 0, sy = 0;
|
|
1216
1261
|
if (field) {
|
|
1217
1262
|
ev.warn("levelset(): a 2D field must be field[i][j]; a 3D array was given",
|
|
1218
1263
|
&node.position());
|
|
1219
1264
|
return {};
|
|
1220
1265
|
}
|
|
1266
|
+
const double x0 = (*bLo)[0], y0 = (*bLo)[1];
|
|
1267
|
+
const double wx = (*bHi)[0] - x0, wy = (*bHi)[1] - y0;
|
|
1268
|
+
double ex = edgeVec ? edgeV[0] : edge, ey = edgeVec ? edgeV[1] : edge;
|
|
1269
|
+
std::optional<std::vector<std::vector<double>>> plane;
|
|
1270
|
+
size_t px = 0, py = 0;
|
|
1271
|
+
bool ownSamples = false;
|
|
1221
1272
|
if (!fieldFn) {
|
|
1222
|
-
|
|
1273
|
+
plane = readPlane(fieldArg);
|
|
1223
1274
|
if (!plane || plane->size() < 2 || (*plane)[0].size() < 2) {
|
|
1224
1275
|
ev.warn("levelset(): 2D field must be a rectangular field[i][j] of numbers",
|
|
1225
1276
|
&node.position());
|
|
1226
1277
|
return {};
|
|
1227
1278
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
g.dx = sx;
|
|
1236
|
-
g.dy = sy;
|
|
1237
|
-
g.ox = (*bLo)[0] - sx;
|
|
1238
|
-
g.oy = (*bLo)[1] - sy;
|
|
1239
|
-
// Padded with a ring that is firmly OUTSIDE, so a contour meeting
|
|
1240
|
-
// the box edge closes along it instead of running off. This is
|
|
1241
|
-
// BOSL2's closed=true, and the only behaviour offered.
|
|
1242
|
-
g.v.assign(g.nx * g.ny, -1.0);
|
|
1243
|
-
for (size_t i = 0; i < nx; ++i)
|
|
1244
|
-
for (size_t j = 0; j < ny; ++j)
|
|
1245
|
-
g.v[(j + 1) * g.nx + (i + 1)] = bandDistance((*plane)[i][j], isoLo, isoHi, invert);
|
|
1246
|
-
const manifold::Polygons polys = marchingSquares(g);
|
|
1247
|
-
if (polys.empty()) return {};
|
|
1248
|
-
ColoredBody b;
|
|
1249
|
-
b.section = clipToBounds(manifold::CrossSection(polys, manifold::CrossSection::FillRule::EvenOdd),
|
|
1250
|
-
*bLo, *bHi);
|
|
1251
|
-
if (b.section->IsEmpty()) return {};
|
|
1252
|
-
std::vector<ColoredBody> out;
|
|
1253
|
-
out.push_back(std::move(b));
|
|
1254
|
-
return out;
|
|
1279
|
+
px = plane->size();
|
|
1280
|
+
py = (*plane)[0].size();
|
|
1281
|
+
// Contoured on its own samples unless edge= asks for another
|
|
1282
|
+
// spacing, as the 3D grid is marched; then re-sampled bilinearly.
|
|
1283
|
+
const double gx = wx / static_cast<double>(px - 1), gy = wy / static_cast<double>(py - 1);
|
|
1284
|
+
const auto same = [](double a, double b) { return std::abs(a - b) <= 1e-9 * std::max(a, b); };
|
|
1285
|
+
ownSamples = ex <= 0.0 || (same(ex, gx) && same(ey, gy));
|
|
1255
1286
|
}
|
|
1256
|
-
//
|
|
1257
|
-
|
|
1258
|
-
nx = static_cast<size_t>(std::floor(
|
|
1259
|
-
ny = static_cast<size_t>(std::floor(
|
|
1287
|
+
// Counted from the array, not floor(width / spacing): rounding there
|
|
1288
|
+
// could drop the last sample row.
|
|
1289
|
+
const size_t nx = ownSamples ? px : static_cast<size_t>(std::floor(wx / ex)) + 1;
|
|
1290
|
+
const size_t ny = ownSamples ? py : static_cast<size_t>(std::floor(wy / ey)) + 1;
|
|
1260
1291
|
if (nx < 2 || ny < 2) {
|
|
1261
1292
|
ev.warn("levelset(): edge is larger than the bounds", &node.position());
|
|
1262
1293
|
return {};
|
|
1263
1294
|
}
|
|
1264
|
-
sx = (
|
|
1265
|
-
|
|
1295
|
+
const double sx = wx / static_cast<double>(nx - 1), sy = wy / static_cast<double>(ny - 1);
|
|
1296
|
+
// The plane at a point between its samples. Clamped at the edges,
|
|
1297
|
+
// like the 3D grid sampler, so the clip below cuts a clean line.
|
|
1298
|
+
const auto bilinear = [&](double x, double y) {
|
|
1299
|
+
const auto cell = [](double u, size_t n, size_t& i0) {
|
|
1300
|
+
i0 = static_cast<size_t>(std::clamp(std::floor(u), 0.0, static_cast<double>(n - 2)));
|
|
1301
|
+
return std::clamp(u - static_cast<double>(i0), 0.0, 1.0);
|
|
1302
|
+
};
|
|
1303
|
+
size_t i, j;
|
|
1304
|
+
const double tx = cell((x - x0) / wx * static_cast<double>(px - 1), px, i);
|
|
1305
|
+
const double ty = cell((y - y0) / wy * static_cast<double>(py - 1), py, j);
|
|
1306
|
+
const auto& p = *plane;
|
|
1307
|
+
return (1 - tx) * ((1 - ty) * p[i][j] + ty * p[i][j + 1])
|
|
1308
|
+
+ tx * ((1 - ty) * p[i + 1][j] + ty * p[i + 1][j + 1]);
|
|
1309
|
+
};
|
|
1266
1310
|
Contours2d g;
|
|
1267
1311
|
g.nx = nx + 2;
|
|
1268
1312
|
g.ny = ny + 2;
|
|
1269
1313
|
g.dx = sx;
|
|
1270
1314
|
g.dy = sy;
|
|
1271
|
-
g.ox =
|
|
1272
|
-
g.oy =
|
|
1315
|
+
g.ox = x0 - sx;
|
|
1316
|
+
g.oy = y0 - sy;
|
|
1317
|
+
// Padded with a ring that is firmly OUTSIDE, so a contour meeting
|
|
1318
|
+
// the box edge closes along it instead of running off. This is
|
|
1319
|
+
// BOSL2's closed=true, and the only behaviour offered.
|
|
1273
1320
|
g.v.assign(g.nx * g.ny, -1.0);
|
|
1274
1321
|
for (size_t i = 0; i < nx; ++i) {
|
|
1275
1322
|
for (size_t j = 0; j < ny; ++j) {
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1323
|
+
const double x = x0 + static_cast<double>(i) * sx, y = y0 + static_cast<double>(j) * sy;
|
|
1324
|
+
double val;
|
|
1325
|
+
if (ownSamples) {
|
|
1326
|
+
val = (*plane)[i][j];
|
|
1327
|
+
} else if (plane) {
|
|
1328
|
+
val = bilinear(x, y);
|
|
1329
|
+
} else {
|
|
1330
|
+
BoundArgs bound;
|
|
1331
|
+
bound.set(fnParams2[0], Value{x});
|
|
1332
|
+
bound.set(fnParams2[1], Value{y});
|
|
1333
|
+
const Value outv =
|
|
1334
|
+
ev.evalFunctionLiteralFromBound(**fieldFn, std::move(bound), *fnCtx, &node.position());
|
|
1335
|
+
val = fieldSample(outv).value_or(std::numeric_limits<double>::max());
|
|
1336
|
+
}
|
|
1282
1337
|
g.v[(j + 1) * g.nx + (i + 1)] = bandDistance(val, isoLo, isoHi, invert);
|
|
1283
1338
|
}
|
|
1284
1339
|
}
|
|
@@ -1374,11 +1374,12 @@ TEST(LevelSetFn, AVectorEdgeOfTheWrongSizeWarns) {
|
|
|
1374
1374
|
|
|
1375
1375
|
TEST(LevelSetFn, SupportedFeatureSaysAVectorEdgeWorks) {
|
|
1376
1376
|
// Level 2 is how a library such as BOSL2 tells a build with per-axis
|
|
1377
|
-
// edge= from one that would reject it
|
|
1377
|
+
// edge= from one that would reject it; level 3, one that places a
|
|
1378
|
+
// field array from edge= alone (#749 on BelfrySCAD).
|
|
1378
1379
|
std::vector<std::string> out;
|
|
1379
1380
|
evalSrc("echo(supported_feature(\"levelset\"));", [&](const std::string& m) { out.push_back(m); });
|
|
1380
1381
|
ASSERT_EQ(out.size(), 1u);
|
|
1381
|
-
EXPECT_NE(out[0].find("
|
|
1382
|
+
EXPECT_NE(out[0].find("3"), std::string::npos) << out[0];
|
|
1382
1383
|
}
|
|
1383
1384
|
|
|
1384
1385
|
TEST(LevelSetFn, AFunctionOfTheWrongArityWarns) {
|
|
@@ -1674,6 +1675,73 @@ TEST(LevelSetGrid, TheDefaultMarchesTheGridItself) {
|
|
|
1674
1675
|
EXPECT_EQ(soleBody(same).NumTri(), soleBody(e).NumTri());
|
|
1675
1676
|
}
|
|
1676
1677
|
|
|
1678
|
+
TEST(LevelSetGrid, EdgeWithoutBoundsCentresTheGridOnTheOrigin) {
|
|
1679
|
+
// #749 on BelfrySCAD: edge= alone places a field array, its samples
|
|
1680
|
+
// edge apart and centred on the origin, as BOSL2's isosurface() places
|
|
1681
|
+
// an array given voxel_size. Same mesh as the explicit bounds.
|
|
1682
|
+
Evaluated e = evalSrc(sphereFieldSrc(41, 20) + "levelset(f, isovalue=15, edge=1);");
|
|
1683
|
+
Evaluated ref = evalSrc(sphereFieldSrc(41, 20) +
|
|
1684
|
+
"levelset(f, bounds=[[-20,-20,-20],[20,20,20]], isovalue=15);");
|
|
1685
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
1686
|
+
ASSERT_EQ(ref.bodies.size(), 1u);
|
|
1687
|
+
EXPECT_EQ(soleBody(e).NumTri(), soleBody(ref).NumTri());
|
|
1688
|
+
EXPECT_NEAR(soleBody(e).Volume(), soleBody(ref).Volume(), 1e-9 * soleBody(ref).Volume());
|
|
1689
|
+
EXPECT_GT(onGridLines(soleBody(e), manifold::vec3(-20.0), manifold::vec3(1.0)), 0.5);
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
TEST(LevelSetGrid, AVectorEdgeWithoutBoundsSpacesEachAxis) {
|
|
1693
|
+
// Every sample inside, so the solid is the whole box: 5 x 3 x 4 samples
|
|
1694
|
+
// at [1, 2, 0.5] span 4 x 4 x 1.5, centred.
|
|
1695
|
+
Evaluated e = evalSrc("f = [for (i=[0:4]) [for (j=[0:2]) [for (k=[0:3]) -1 ]]];\n"
|
|
1696
|
+
"levelset(f, edge=[1, 2, 0.5]);");
|
|
1697
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
1698
|
+
const manifold::Box b = soleBody(e).BoundingBox();
|
|
1699
|
+
EXPECT_NEAR(b.min.x, -2.0, 1e-9); EXPECT_NEAR(b.max.x, 2.0, 1e-9);
|
|
1700
|
+
EXPECT_NEAR(b.min.y, -2.0, 1e-9); EXPECT_NEAR(b.max.y, 2.0, 1e-9);
|
|
1701
|
+
EXPECT_NEAR(b.min.z, -0.75, 1e-9); EXPECT_NEAR(b.max.z, 0.75, 1e-9);
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
TEST(LevelSetGrid, A2DFieldArrayIsPlacedByEdgeToo) {
|
|
1705
|
+
// field[i][j] says 2D without a bounds to say so.
|
|
1706
|
+
Evaluated e = evalSrc("f = [for (i=[0:4]) [for (j=[0:2]) -1 ]];\nlevelset(f, edge=2);");
|
|
1707
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
1708
|
+
ASSERT_TRUE(e.bodies[0].section.has_value());
|
|
1709
|
+
const manifold::Rect r = e.bodies[0].section->Bounds();
|
|
1710
|
+
EXPECT_NEAR(r.min.x, -4.0, 1e-9); EXPECT_NEAR(r.max.x, 4.0, 1e-9);
|
|
1711
|
+
EXPECT_NEAR(r.min.y, -2.0, 1e-9); EXPECT_NEAR(r.max.y, 2.0, 1e-9);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
TEST(LevelSetGrid, A2DGridIsResampledAtADifferentEdge) {
|
|
1715
|
+
// As in 3D: edge= beside bounds re-samples the plane (bilinearly), where
|
|
1716
|
+
// it used to be ignored. A cone sampled every 2, contoured at r=7.
|
|
1717
|
+
const std::string field =
|
|
1718
|
+
"f = [for (i=[0:10]) [for (j=[0:10]) let(x=-10+2*i, y=-10+2*j) sqrt(x*x+y*y) ]];\n";
|
|
1719
|
+
const std::string box = "bounds=[[-10,-10],[10,10]], isovalue=7";
|
|
1720
|
+
Evaluated own = evalSrc(field + "levelset(f, " + box + ");");
|
|
1721
|
+
Evaluated same = evalSrc(field + "levelset(f, " + box + ", edge=2);");
|
|
1722
|
+
Evaluated fine = evalSrc(field + "levelset(f, " + box + ", edge=0.25);");
|
|
1723
|
+
for (Evaluated* e : {&own, &same, &fine}) {
|
|
1724
|
+
ASSERT_EQ(e->bodies.size(), 1u);
|
|
1725
|
+
ASSERT_TRUE(e->bodies[0].section.has_value());
|
|
1726
|
+
}
|
|
1727
|
+
EXPECT_EQ(same.bodies[0].section->NumVert(), own.bodies[0].section->NumVert());
|
|
1728
|
+
EXPECT_GT(fine.bodies[0].section->NumVert(), 4 * own.bodies[0].section->NumVert());
|
|
1729
|
+
const double disc = 3.14159265358979 * 49;
|
|
1730
|
+
EXPECT_NEAR(fine.bodies[0].section->Area(), disc, 0.03 * disc);
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
TEST(LevelSetGrid, NeitherBoundsNorEdgeSaysWhatIsMissing) {
|
|
1734
|
+
const std::vector<std::string> w =
|
|
1735
|
+
levelsetWarnings("f = [for (i=[0:4]) [for (j=[0:2]) [for (k=[0:3]) -1 ]]];\nlevelset(f);");
|
|
1736
|
+
ASSERT_EQ(w.size(), 1u);
|
|
1737
|
+
EXPECT_NE(w[0].find("bounds=, or edge="), std::string::npos) << w[0];
|
|
1738
|
+
// A function field has no sizes to infer from: bounds stays required.
|
|
1739
|
+
const std::vector<std::string> fw =
|
|
1740
|
+
levelsetWarnings("levelset(function(x,y,z) x, edge=1);");
|
|
1741
|
+
ASSERT_EQ(fw.size(), 1u);
|
|
1742
|
+
EXPECT_NE(fw[0].find("bounds must be"), std::string::npos) << fw[0];
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1677
1745
|
TEST(LevelSetGrid, ADifferentEdgeStillResamples) {
|
|
1678
1746
|
Evaluated e = evalSrc(sphereFieldSrc(41, 20) +
|
|
1679
1747
|
"levelset(f, bounds=[[-20,-20,-20],[20,20,20]], isovalue=15, edge=0.7);");
|
|
File without changes
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/.github/workflows/wheels.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.47.0 → openscad_cpp_evaluator-1.48.0}/external/openscad_cpp_parser/LICENSE
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
|
|
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
|
|
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
|