openscad-cpp-evaluator 1.45.0__tar.gz → 1.45.2__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.45.0 → openscad_cpp_evaluator-1.45.2}/CLAUDE.md +4 -1
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/PKG-INFO +1 -1
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/mesh_import.hpp +3 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/pyproject.toml +1 -1
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/roof.cpp +81 -20
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/import/scene_import.cpp +14 -5
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_extrude_roof.cpp +79 -2
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_import_export.cpp +93 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/uv.lock +1 -1
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/.github/workflows/wheels.yml +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/.gitignore +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/.gitmodules +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/LICENSE +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/README.md +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/bindings/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/bindings/ast_to_py.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/bindings/module.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/cmake/embed_font.cmake +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/cmake/patch_manifold.cmake +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/eval_perf_benchmark.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/manifold_cache_reuse.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/minimal_debugger.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/.github/workflows/ci.yml +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/.gitignore +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/CLAUDE.md +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/LICENSE +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/README.md +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/api.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/ast_node.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/declarations.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/expression.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/module_instantiation.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/scope_builder.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast/vector_element.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/ast.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/comments.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/position.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/pretty_print.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/scope_table.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/serialization.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/include/openscad_cpp_parser/source_map.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/.DS_Store +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/api.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/ast_node.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/declarations.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/expression.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/format_utils.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/module_instantiation.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/scope_builder.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/ast/vector_element.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/comment_attach_internal.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/comments.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/driver.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/driver.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/lexer.l +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/lexer_api.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/oscad_location.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/grammar/parser.y +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/inline_comment_attach.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/position.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/scope.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/serialization/json_io.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/serialization/yaml_io.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/src/source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_assignments.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_ast_generation.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_comments_and_files.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_concurrent_parse.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_const_borrow.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_control.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_expressions.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_functions.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_inline_comments.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_lexical.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_modules.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_node_str.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_pretty_print.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_render_expression.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_scope.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_serialization.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_smoke.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_source_map.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_strict_commas.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_use_include.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tests/test_vectors.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/external/openscad_cpp_parser/tools/cli/main.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/bound_args.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/bytecode.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/bytecode_compiler.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/bytecode_vm.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/call_args.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/colored_body.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/coverage.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/csg_node.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/css_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/debug_hooks.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/debug_repl.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/dispatch.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/dxf_svg_import.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/eval_context.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/eval_error.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/eval_use.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/evaluator.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/export.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/font_match.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/format_closure.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/freetype_font_provider.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/function_builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/import_builtin.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/manifold_cache.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/mesh_check.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/osc_range.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/profile.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/scope_trail.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/segments.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/surface_load.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/text_metrics.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/utf8.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/value.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/include/openscad_cpp_evaluator/zip_stored.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/python/openscad_cpp_evaluator/__init__.py +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/resources/fonts/LICENSE +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/resources/fonts/LiberationSans-Bold.ttf +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/resources/fonts/LiberationSans-BoldItalic.ttf +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/resources/fonts/LiberationSans-Italic.ttf +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/resources/fonts/LiberationSans-Regular.ttf +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/builtins.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/call_args.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/color.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/control.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/dxf_dim.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/extrude.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/import.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/modifiers.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/primitives_2d.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/primitives_3d.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/registry.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/segments.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/surface.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/text.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/topology.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/builtins/transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/bytecode_vm.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/colored_body.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/csg_generate.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/csg_resolve.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/css_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/debug/debug_repl.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/debug_profile.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/eval_error.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/eval_use.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/export.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/format_closure.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/import/dxf_import.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/import/mesh_import.cpp +12 -12
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/import/surface_load.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/import/svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/measure_geometry.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/stmt_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/text/font_match.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/text/freetype_font_provider.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/text/text_metrics.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/user_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/utf8.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/value.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/xkcd_colors.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/xkcd_colors.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/src/zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_booleans.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_bytecode_compiler.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_children_separate.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_cli.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_control_flow.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_coverage.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_csg_tree.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_debug_hooks.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_discretizer.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_dxf_svg_import.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_eval_context.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_export.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_expr_eval.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_feature_detection.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_function_builtins.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_helpers.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_include_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_manifold_cache.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_mesh_check.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_multi_color_merge.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_openscad_parity.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_primitives.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_profile_time.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_profiling.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_python_bindings.py +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_render_expr.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_scope_trail.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_scoping.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_surface.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_tail_calls.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_text.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_transforms.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_undef_args.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_unexpected_args.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_use.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_value.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_viewport_params.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_zip_stored.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tools/cli/CMakeLists.txt +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tools/cli/cli_lib.cpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tools/cli/cli_lib.hpp +0 -0
- {openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tools/cli/main.cpp +0 -0
|
@@ -1247,7 +1247,10 @@ grep for `ponytail:`.
|
|
|
1247
1247
|
without `-1` counts), and X3D's `IndexedTriangleSet`/`TriangleSet` are read. X3D goes through a
|
|
1248
1248
|
small real XML parser (comments, CDATA, DOCTYPE, entities); VRML through a tokenizer + generic
|
|
1249
1249
|
node parser that steps over `PROTO`/`EXTERNPROTO`/`ROUTE` (VRML 1.0 is refused by name). AMF's
|
|
1250
|
-
`unit`
|
|
1250
|
+
`unit` is ignored (OpenSCAD reads millimetres whatever it says), a zipped AMF (`PK` header) is read
|
|
1251
|
+
through `readStoredZipEntryBySuffix`, and each AMF object's vertices are welded by exact position
|
|
1252
|
+
(`weldVertices`, STL's), so a closed object written as a triangle soup imports closed, as in
|
|
1253
|
+
OpenSCAD -- per object, never across objects, and never near-coincident vertices.
|
|
1251
1254
|
What is not a mesh — primitives (Box, Sphere, ...), `Inline`, AMF constellations — lands in
|
|
1252
1255
|
`LoadedMesh::warnings`, which both `import()` faces emit as `import: '<file>': ...`.
|
|
1253
1256
|
- `include/openscad_cpp_evaluator/import_builtin.hpp`, `include/openscad_cpp_evaluator/
|
|
@@ -22,6 +22,9 @@ struct LoadedMesh {
|
|
|
22
22
|
// "import: {what}" on parse/IO failure. Mirrors _load_stl/_load_obj/
|
|
23
23
|
// _load_off/_load_3mf exactly (including STL's exact-match vertex welding
|
|
24
24
|
// and OBJ/OFF's fan triangulation of >3-gon faces).
|
|
25
|
+
// Merges vertices at exactly equal positions (STL's corners, an AMF
|
|
26
|
+
// object's duplicated vertices); every position keeps its first index.
|
|
27
|
+
LoadedMesh weldVertices(const std::vector<std::array<double, 3>>& verts, const std::vector<std::array<int, 3>>& tris);
|
|
25
28
|
LoadedMesh loadStl(const std::string& path);
|
|
26
29
|
LoadedMesh loadObj(const std::string& path);
|
|
27
30
|
LoadedMesh loadOff(const std::string& path);
|
|
@@ -114,10 +114,35 @@ class RoofMesh {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
// A vertex no triangle uses -- the far end of an unbounded Voronoi edge
|
|
118
|
+
// outside the outline can lie 10^12 away -- would stretch the bounding
|
|
119
|
+
// box Manifold sizes its tolerance by, and its cleanup would then
|
|
120
|
+
// collapse the whole roof; such vertices are left out. (Only when one
|
|
121
|
+
// lies well beyond the rest: renumbering reorders the output, and one
|
|
122
|
+
// nearer changes the tolerance by no more than a few times.)
|
|
117
123
|
manifold::Manifold build() {
|
|
118
124
|
mesh_.numProp = 3;
|
|
125
|
+
const size_t n = mesh_.vertProperties.size() / 3;
|
|
126
|
+
std::vector<bool> used(n, false);
|
|
119
127
|
for (const auto& t : triangles_) {
|
|
120
|
-
for (int i : t)
|
|
128
|
+
for (int i : t) used[i] = true;
|
|
129
|
+
}
|
|
130
|
+
manifold::Box box;
|
|
131
|
+
for (size_t i = 0; i < n; ++i) {
|
|
132
|
+
if (used[i]) box.Union(manifold::vec3(mesh_.vertProperties[3 * i], mesh_.vertProperties[3 * i + 1], mesh_.vertProperties[3 * i + 2]));
|
|
133
|
+
}
|
|
134
|
+
std::vector<uint64_t> to(n);
|
|
135
|
+
std::vector<double> kept;
|
|
136
|
+
bool stray = false;
|
|
137
|
+
for (size_t i = 0; i < n; ++i) {
|
|
138
|
+
const manifold::vec3 p(mesh_.vertProperties[3 * i], mesh_.vertProperties[3 * i + 1], mesh_.vertProperties[3 * i + 2]);
|
|
139
|
+
stray = stray || (!used[i] && la::maxelem(la::abs(p)) > 16 * box.Scale());
|
|
140
|
+
to[i] = kept.size() / 3;
|
|
141
|
+
if (used[i]) kept.insert(kept.end(), {p.x, p.y, p.z});
|
|
142
|
+
}
|
|
143
|
+
if (stray) mesh_.vertProperties = std::move(kept);
|
|
144
|
+
for (const auto& t : triangles_) {
|
|
145
|
+
for (int i : t) mesh_.triVerts.push_back(stray ? to[i] : static_cast<uint64_t>(i));
|
|
121
146
|
}
|
|
122
147
|
manifold::Manifold body(mesh_);
|
|
123
148
|
if (body.Status() == manifold::Manifold::Error::NoError) return body;
|
|
@@ -991,16 +1016,17 @@ void dropSpikes(std::vector<Vec2>& c) {
|
|
|
991
1016
|
}
|
|
992
1017
|
}
|
|
993
1018
|
|
|
994
|
-
// The outline of `cs` snapped to a grid of 2^
|
|
995
|
-
// coordinate, with repeated and straight corners dropped. Sets
|
|
996
|
-
|
|
1019
|
+
// The outline of `cs` snapped to a grid of 2^(bits+1) steps across its
|
|
1020
|
+
// largest coordinate, with repeated and straight corners dropped. Sets
|
|
1021
|
+
// `toGrid`.
|
|
1022
|
+
std::vector<std::vector<Vec2>> gridContours(const manifold::CrossSection& cs, double& toGrid, int bits = 29) {
|
|
997
1023
|
const manifold::Polygons polys = cs.ToPolygons();
|
|
998
1024
|
double extent = 0;
|
|
999
1025
|
for (const auto& poly : polys) {
|
|
1000
1026
|
for (Vec2 p : poly) extent = std::max({extent, std::abs(p.x), std::abs(p.y)});
|
|
1001
1027
|
}
|
|
1002
1028
|
if (!(extent > 0) || !std::isfinite(extent)) return {};
|
|
1003
|
-
toGrid = std::ldexp(1.0,
|
|
1029
|
+
toGrid = std::ldexp(1.0, bits - std::ilogb(extent));
|
|
1004
1030
|
|
|
1005
1031
|
std::vector<std::vector<Vec2>> contours;
|
|
1006
1032
|
for (const auto& poly : polys) {
|
|
@@ -1016,17 +1042,6 @@ std::vector<std::vector<Vec2>> gridContours(const manifold::CrossSection& cs, do
|
|
|
1016
1042
|
return contours;
|
|
1017
1043
|
}
|
|
1018
1044
|
|
|
1019
|
-
// The roof solid over `cs` (its floor at z = 0), discretizing curved parts
|
|
1020
|
-
// by `fa`/`fs`.
|
|
1021
|
-
manifold::Manifold voronoiRoof(const manifold::CrossSection& cs, double fa, double fs) {
|
|
1022
|
-
double toGrid = 1;
|
|
1023
|
-
std::vector<std::vector<Vec2>> contours = gridContours(cs, toGrid);
|
|
1024
|
-
if (contours.empty()) return manifold::Manifold();
|
|
1025
|
-
// $fa/$fs below 0.01 would ask for unbounded detail (computeRoofParams
|
|
1026
|
-
// has already clamped them, warning).
|
|
1027
|
-
return RoofBuilder(std::move(contours), 1 / toGrid, std::max(fa, 0.01), std::max(fs, 0.01)).build();
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
1045
|
// The outline welded where it touches itself: a union can leave pieces
|
|
1031
1046
|
// that share an edge, or a hole against the outline, as outlines a hairline
|
|
1032
1047
|
// apart, crossing at nothing Clipper can see. Each corner within kWeld of
|
|
@@ -1062,8 +1077,11 @@ std::vector<std::vector<Vec2>> weldContours(std::vector<std::vector<Vec2>> conto
|
|
|
1062
1077
|
}
|
|
1063
1078
|
}
|
|
1064
1079
|
}
|
|
1065
|
-
//
|
|
1066
|
-
//
|
|
1080
|
+
// Each edge looks only at the corners in its x range.
|
|
1081
|
+
// ponytail: still O(n^2) for an outline of long edges all spanning one
|
|
1082
|
+
// x range; a grid of edges if that ever matters.
|
|
1083
|
+
const auto byX = [](Vec2 p, Vec2 q) { return p.x != q.x ? p.x < q.x : p.y < q.y; };
|
|
1084
|
+
std::sort(corners.begin(), corners.end(), byX);
|
|
1067
1085
|
Clipper2Lib::Paths64 paths;
|
|
1068
1086
|
for (const auto& c : contours) {
|
|
1069
1087
|
Clipper2Lib::Path64 path;
|
|
@@ -1074,8 +1092,10 @@ std::vector<std::vector<Vec2>> weldContours(std::vector<std::vector<Vec2>> conto
|
|
|
1074
1092
|
if (len == 0) continue;
|
|
1075
1093
|
const Vec2 lo = la::min(a, b) - kWeld, hi = la::max(a, b) + kWeld;
|
|
1076
1094
|
std::vector<std::pair<double, Vec2>> on;
|
|
1077
|
-
for (
|
|
1078
|
-
|
|
1095
|
+
for (auto it = std::lower_bound(corners.begin(), corners.end(), Vec2{lo.x, -std::numeric_limits<double>::infinity()}, byX);
|
|
1096
|
+
it != corners.end() && it->x <= hi.x; ++it) {
|
|
1097
|
+
const Vec2 q = *it;
|
|
1098
|
+
if (q.y < lo.y || q.y > hi.y || q == a || q == b) continue;
|
|
1079
1099
|
const double t = la::dot(q - a, d) / len;
|
|
1080
1100
|
if (t > 0 && t < len && std::abs(cross2(d, q - a)) / len <= kWeld) on.push_back({t, q});
|
|
1081
1101
|
}
|
|
@@ -1095,6 +1115,47 @@ std::vector<std::vector<Vec2>> weldContours(std::vector<std::vector<Vec2>> conto
|
|
|
1095
1115
|
return welded;
|
|
1096
1116
|
}
|
|
1097
1117
|
|
|
1118
|
+
// Each contour rotated to start at its least corner, and the contours sorted:
|
|
1119
|
+
// equal for two outlines that differ only in where Clipper starts them.
|
|
1120
|
+
std::vector<std::vector<Vec2>> canonical(std::vector<std::vector<Vec2>> contours) {
|
|
1121
|
+
const auto less = [](Vec2 a, Vec2 b) { return a.x != b.x ? a.x < b.x : a.y < b.y; };
|
|
1122
|
+
for (auto& c : contours) std::rotate(c.begin(), std::min_element(c.begin(), c.end(), less), c.end());
|
|
1123
|
+
std::sort(contours.begin(), contours.end(), [&](const auto& a, const auto& b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), less); });
|
|
1124
|
+
return contours;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// The roof solid over `cs` (its floor at z = 0), discretizing curved parts
|
|
1128
|
+
// by `fa`/`fs`.
|
|
1129
|
+
//
|
|
1130
|
+
// Boost's Voronoi builder needs segments that meet only at their ends. A
|
|
1131
|
+
// union's pieces sharing an edge come back as outlines a hairline apart,
|
|
1132
|
+
// which on the grid overlap or cross: the diagram comes out wrong, or the
|
|
1133
|
+
// builder never finishes, allocating without bound. So the outline is
|
|
1134
|
+
// welded first, as for the straight skeleton.
|
|
1135
|
+
//
|
|
1136
|
+
// Even on valid input the builder occasionally gets a near-degenerate
|
|
1137
|
+
// configuration wrong -- a cell left with no finite edges, where four sites
|
|
1138
|
+
// are all but equidistant once the outline is rounded to the grid -- and the
|
|
1139
|
+
// facets built from it do not close. Rounding to a coarser grid perturbs
|
|
1140
|
+
// the outline differently, so the roof is retried there.
|
|
1141
|
+
manifold::Manifold voronoiRoof(const manifold::CrossSection& cs, double fa, double fs) {
|
|
1142
|
+
manifold::Manifold body;
|
|
1143
|
+
for (int bits = 29; bits >= 25; --bits) {
|
|
1144
|
+
double toGrid = 1;
|
|
1145
|
+
std::vector<std::vector<Vec2>> contours = gridContours(cs, toGrid, bits);
|
|
1146
|
+
std::vector<std::vector<Vec2>> welded = weldContours(contours);
|
|
1147
|
+
// An outline welding leaves as it was keeps its own order, so its
|
|
1148
|
+
// roof is the same, vertex for vertex, as without welding.
|
|
1149
|
+
if (canonical(welded) != canonical(contours)) contours = std::move(welded);
|
|
1150
|
+
if (contours.empty()) return manifold::Manifold();
|
|
1151
|
+
// $fa/$fs below 0.01 would ask for unbounded detail
|
|
1152
|
+
// (computeRoofParams has already clamped them, warning).
|
|
1153
|
+
body = RoofBuilder(std::move(contours), 1 / toGrid, std::max(fa, 0.01), std::max(fs, 0.01)).build();
|
|
1154
|
+
if (body.Status() == manifold::Manifold::Error::NoError && !body.IsEmpty()) break;
|
|
1155
|
+
}
|
|
1156
|
+
return body;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1098
1159
|
manifold::Manifold straightRoof(const manifold::CrossSection& cs) {
|
|
1099
1160
|
double toGrid = 1;
|
|
1100
1161
|
std::vector<std::vector<Vec2>> contours = weldContours(gridContours(cs, toGrid));
|
|
@@ -653,13 +653,13 @@ LoadedMesh loadAmf(const std::string& path) {
|
|
|
653
653
|
LoadedMesh out;
|
|
654
654
|
for (std::string_view object : segments(xml, "object")) {
|
|
655
655
|
const std::string_view verticesBlock = elementText(object, "vertices");
|
|
656
|
-
|
|
656
|
+
LoadedMesh obj;
|
|
657
657
|
for (std::string_view vertex : segments(verticesBlock, "vertex")) {
|
|
658
658
|
const std::string_view c = elementText(vertex, "coordinates");
|
|
659
|
-
|
|
659
|
+
obj.verts.push_back({amfNumber(elementText(c, "x"), "x") * unit, amfNumber(elementText(c, "y"), "y") * unit,
|
|
660
660
|
amfNumber(elementText(c, "z"), "z") * unit});
|
|
661
661
|
}
|
|
662
|
-
const int count = static_cast<int>(
|
|
662
|
+
const int count = static_cast<int>(obj.verts.size());
|
|
663
663
|
for (std::string_view volume : segments(object, "volume")) {
|
|
664
664
|
for (std::string_view tri : segments(volume, "triangle")) {
|
|
665
665
|
std::array<int, 3> t{};
|
|
@@ -669,11 +669,20 @@ LoadedMesh loadAmf(const std::string& path) {
|
|
|
669
669
|
if (i < 0 || i >= count)
|
|
670
670
|
throw std::runtime_error("AMF: triangle vertex " + std::to_string(i) + " is past its object's " +
|
|
671
671
|
std::to_string(count) + " vertices");
|
|
672
|
-
t[k] =
|
|
672
|
+
t[k] = i;
|
|
673
673
|
}
|
|
674
|
-
|
|
674
|
+
obj.tris.push_back(t);
|
|
675
675
|
}
|
|
676
676
|
}
|
|
677
|
+
// OpenSCAD treats vertices at exactly the same position as one
|
|
678
|
+
// (checked, 2026.02.01): a closed object written as a triangle soup,
|
|
679
|
+
// or with its vertices listed twice, imports as a closed solid.
|
|
680
|
+
// Within each object only -- two open halves in separate objects
|
|
681
|
+
// stay open there too. Near-coincident vertices are not merged.
|
|
682
|
+
obj = weldVertices(obj.verts, obj.tris);
|
|
683
|
+
const int base = static_cast<int>(out.verts.size());
|
|
684
|
+
out.verts.insert(out.verts.end(), obj.verts.begin(), obj.verts.end());
|
|
685
|
+
for (const auto& t : obj.tris) out.tris.push_back({base + t[0], base + t[1], base + t[2]});
|
|
677
686
|
}
|
|
678
687
|
if (xml.find("<constellation") != std::string::npos) {
|
|
679
688
|
out.warnings.push_back("AMF constellations are not applied: each object is imported where it was modeled");
|
|
@@ -347,8 +347,8 @@ struct RoofResult {
|
|
|
347
347
|
double slopeError; // roof area / (floor area * sqrt 2) - 1: 0 if every face rises at 45 degrees
|
|
348
348
|
};
|
|
349
349
|
|
|
350
|
-
RoofResult straightRoof(const std::string& shape) {
|
|
351
|
-
Evaluated e = evalSrc("roof(method=\"
|
|
350
|
+
RoofResult straightRoof(const std::string& shape, const std::string& method = "straight") {
|
|
351
|
+
Evaluated e = evalSrc("roof(method=\"" + method + "\") " + shape);
|
|
352
352
|
EXPECT_EQ(e.bodies.size(), 1u);
|
|
353
353
|
if (e.bodies.empty() || !e.bodies[0].body) return {0, 0, manifold::Manifold::Error::InvalidConstruction, 1};
|
|
354
354
|
const manifold::Manifold& m = *e.bodies[0].body;
|
|
@@ -463,6 +463,83 @@ TEST(Roof, StraightHandlesThousandsOfVertices) {
|
|
|
463
463
|
EXPECT_NEAR(g.slopeError, 0, 1e-5);
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
+
// -- method="voronoi" over unions of pieces that touch along edges. These
|
|
467
|
+
// all gave no roof at all before: Clipper returns the pieces as outlines a
|
|
468
|
+
// hairline apart, which on the grid overlap or cross, and Boost's Voronoi
|
|
469
|
+
// builder needs segments that meet only at their ends.
|
|
470
|
+
|
|
471
|
+
namespace {
|
|
472
|
+
|
|
473
|
+
void expectVoronoiRoof(const std::string& shape, double volume, double height, double tol) {
|
|
474
|
+
SCOPED_TRACE(shape);
|
|
475
|
+
const RoofResult r = straightRoof(shape, "voronoi");
|
|
476
|
+
EXPECT_EQ(r.status, manifold::Manifold::Error::NoError);
|
|
477
|
+
EXPECT_NEAR(r.volume, volume, tol * volume);
|
|
478
|
+
EXPECT_NEAR(r.height, height, tol);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
} // namespace
|
|
482
|
+
|
|
483
|
+
// Four triangles sharing edges. The reference agrees: 23.67785 / 2.39894.
|
|
484
|
+
TEST(Roof, VoronoiJoinsTrianglesThatShareEdges) {
|
|
485
|
+
expectVoronoiRoof("union() { polygon([[2.764760357, 4.118581106], [5.901400476, 6.372929785], [8.606126287, 1.988496895]]); "
|
|
486
|
+
"polygon([[5.901400476, 6.372929785], [8.606126287, 1.988496895], [11.028736411, 6.50946765]]); "
|
|
487
|
+
"polygon([[8.606126287, 1.988496895], [2.764760357, 4.118581106], [4.975336337, 1.106200614]]); "
|
|
488
|
+
"polygon([[8.606126287, 1.988496895], [2.764760357, 4.118581106], [6.985603416, 6.618989998]]); }",
|
|
489
|
+
23.677855, 2.39894, 1e-5);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Rotated rectangles sharing (parts of) edges. OpenSCAD 2026.02.01 draws
|
|
493
|
+
// nothing for it; the volume is the integral of the distance to the outline
|
|
494
|
+
// to within the faceting of the cones (170.68 numerically).
|
|
495
|
+
TEST(Roof, VoronoiJoinsRotatedRectanglesThatShareEdges) {
|
|
496
|
+
expectVoronoiRoof("union() { polygon([[-3.369828352, 0.413896268], [-7.46233132, 4.010047378], [-11.05848243, -0.08245559], [-6.965979462, -3.6786067]]); "
|
|
497
|
+
"polygon([[-4.919727978, -5.476682255], [-9.012230946, -1.880531145], [-14.406457611, -8.019285597], [-10.313954643, -11.615436707]]); "
|
|
498
|
+
"polygon([[6.613253139, -4.732154468], [0.474498687, 0.662072197], [-4.919727978, -5.476682255], [1.219026474, -10.87090892]]); "
|
|
499
|
+
"polygon([[10.457580178, -4.483978539], [8.411328694, -2.685902984], [6.613253139, -4.732154468], [8.659504623, -6.530230023]]); }",
|
|
500
|
+
170.76468, 4.08601, 1e-5);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Here the outline as Clipper leaves it crosses itself on the grid, and the
|
|
504
|
+
// Voronoi builder never finished, allocating until the process was killed
|
|
505
|
+
// (tens of gigabytes). (The integral of the distance to the outline is
|
|
506
|
+
// 221.3; the cones over corners meeting head on are faceted coarsely, as by
|
|
507
|
+
// the reference.)
|
|
508
|
+
TEST(Roof, VoronoiRoofOfACrossingOutlineStaysBounded) {
|
|
509
|
+
expectVoronoiRoof("union() { polygon([[8.304902057, -8.407695464], [0.596294574, -9.683488249], [1.872087359, -17.392095732], [9.580694842, -16.116302947]]); "
|
|
510
|
+
"polygon([[14.737716755, 0.576704804], [7.029109272, -0.699087981], [8.304902057, -8.407695464], [16.01350954, -7.131902679]]); "
|
|
511
|
+
"polygon([[8.304902057, -8.407695464], [-3.258009167, -10.321384641], [-2.620112775, -14.175688383], [8.94279845, -12.261999205]]); "
|
|
512
|
+
"polygon([[2.536909139, 2.517319368], [-1.317394603, 1.879422976], [0.596294574, -9.683488249], [4.450598316, -9.045591856]]); }",
|
|
513
|
+
222.74776, 3.90673, 1e-5);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// A staircase of triangles. Outside it, two of its edges are all but
|
|
517
|
+
// parallel, so their Voronoi bisectors meet some 10^12 away; that vertex,
|
|
518
|
+
// used by no facet, stretched the bounding box Manifold sizes its tolerance
|
|
519
|
+
// by, and its cleanup collapsed the whole roof to nothing. (The integral of
|
|
520
|
+
// the distance to the outline is 78.02.)
|
|
521
|
+
TEST(Roof, VoronoiRoofIgnoresFarVoronoiVertices) {
|
|
522
|
+
expectVoronoiRoof("union() { polygon([[-1.015413575, -0.344245093], [-1.006343725, -5.505019653], [4.154430835, -5.495949802]]); "
|
|
523
|
+
"polygon([[-1.015413575, -0.344245093], [4.154430835, -5.495949802], [4.145360985, -0.335175242]]); "
|
|
524
|
+
"polygon([[-1.006343725, -5.505019653], [4.163500685, -10.656724363], [4.154430835, -5.495949802]]); "
|
|
525
|
+
"polygon([[4.154430835, -5.495949802], [4.163500685, -10.656724363], [9.324275246, -10.647654512]]); "
|
|
526
|
+
"polygon([[4.163500685, -10.656724363], [9.333345096, -15.808429072], [9.324275246, -10.647654512]]); "
|
|
527
|
+
"polygon([[-6.176188135, -0.353314943], [-1.006343725, -5.505019653], [-1.015413575, -0.344245093]]); }",
|
|
528
|
+
78.047622, 3.02312, 1e-5);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// Axis-aligned rectangles: a clean outline, but rounded to the grid four
|
|
532
|
+
// sites are all but equidistant at one point, and Boost's builder leaves a
|
|
533
|
+
// cell with no finite edges. A coarser grid rounds it differently.
|
|
534
|
+
// OpenSCAD 2026.02.01 draws nothing here either; the integral of the
|
|
535
|
+
// distance to the outline is 1.348 (the faceted cone sits a little above).
|
|
536
|
+
TEST(Roof, VoronoiRetriesWhereTheBuilderFails) {
|
|
537
|
+
expectVoronoiRoof("union() { polygon([[0.7, -0.7], [2.1, -0.7], [2.1, 0.0], [0.7, 0.0]]); "
|
|
538
|
+
"polygon([[2.1, -0.7], [2.8, -0.7], [2.8, 0.7], [2.1, 0.7]]); "
|
|
539
|
+
"polygon([[2.8, -1.4], [4.2, -1.4], [4.2, 0.7], [2.8, 0.7]]); }",
|
|
540
|
+
1.3513906, 0.820101, 1e-5);
|
|
541
|
+
}
|
|
542
|
+
|
|
466
543
|
TEST(Roof, UnknownMethodWarnsAndFallsBackToVoronoi) {
|
|
467
544
|
std::string lastWarning;
|
|
468
545
|
Evaluated e = evalSrc("roof(method=\"bogus\") square(4, center=true);", [&](const std::string& msg) { lastWarning = msg; });
|
{openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/tests/test_import_export.cpp
RENAMED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
#include "test_helpers.hpp"
|
|
6
6
|
|
|
7
|
+
#include <algorithm>
|
|
7
8
|
#include <filesystem>
|
|
9
|
+
#include <map>
|
|
8
10
|
#include <fstream>
|
|
9
11
|
#include <gtest/gtest.h>
|
|
10
12
|
#include <manifold/manifold.h>
|
|
@@ -267,6 +269,97 @@ TEST(ImportModuleContext, ZippedAmfImports) {
|
|
|
267
269
|
EXPECT_NEAR(e.bodies[0].body->Volume(), 1.0, 1e-9);
|
|
268
270
|
}
|
|
269
271
|
|
|
272
|
+
namespace {
|
|
273
|
+
|
|
274
|
+
using Tri = std::array<std::array<double, 3>, 3>;
|
|
275
|
+
|
|
276
|
+
// The unit cube at (x, y, z) as 12 outward triangles, two per face, the
|
|
277
|
+
// faces in -z, +z, -y, +x, +y, -x order.
|
|
278
|
+
std::vector<Tri> cubeTris(double x, double y, double z) {
|
|
279
|
+
const int idx[12][3] = {{0, 3, 2}, {0, 2, 1}, {4, 5, 6}, {4, 6, 7}, {0, 1, 5}, {0, 5, 4},
|
|
280
|
+
{1, 2, 6}, {1, 6, 5}, {2, 3, 7}, {2, 7, 6}, {3, 0, 4}, {3, 4, 7}};
|
|
281
|
+
const double c[8][3] = {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}};
|
|
282
|
+
std::vector<Tri> out;
|
|
283
|
+
for (const auto& t : idx) {
|
|
284
|
+
Tri tri;
|
|
285
|
+
for (int k = 0; k < 3; ++k) tri[k] = {c[t[k]][0] + x, c[t[k]][1] + y, c[t[k]][2] + z};
|
|
286
|
+
out.push_back(tri);
|
|
287
|
+
}
|
|
288
|
+
return out;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// One <object> per entry, every triangle carrying its own three vertex
|
|
292
|
+
// copies: a triangle soup, as an exporter that never shares vertices writes.
|
|
293
|
+
std::string soupAmf(const std::vector<std::vector<Tri>>& objects) {
|
|
294
|
+
std::string amf = "<?xml version=\"1.0\"?>\n<amf unit=\"millimeter\">";
|
|
295
|
+
for (const auto& tris : objects) {
|
|
296
|
+
amf += "<object id=\"1\"><mesh><vertices>";
|
|
297
|
+
for (const Tri& t : tris)
|
|
298
|
+
for (const auto& p : t)
|
|
299
|
+
amf += "<vertex><coordinates><x>" + std::to_string(p[0]) + "</x><y>" + std::to_string(p[1]) +
|
|
300
|
+
"</y><z>" + std::to_string(p[2]) + "</z></coordinates></vertex>";
|
|
301
|
+
amf += "</vertices><volume>";
|
|
302
|
+
for (size_t i = 0; i < tris.size(); ++i)
|
|
303
|
+
amf += "<triangle><v1>" + std::to_string(3 * i) + "</v1><v2>" + std::to_string(3 * i + 1) + "</v2><v3>" +
|
|
304
|
+
std::to_string(3 * i + 2) + "</v3></triangle>";
|
|
305
|
+
amf += "</volume></mesh></object>";
|
|
306
|
+
}
|
|
307
|
+
return amf + "</amf>";
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
} // namespace
|
|
311
|
+
|
|
312
|
+
// OpenSCAD treats an AMF object's vertices at exactly the same position as
|
|
313
|
+
// one vertex (checked, 2026.02.01), so a closed object written as a soup
|
|
314
|
+
// imports as a closed solid. Without the weld it was an open surface with
|
|
315
|
+
// 36 boundary edges, drawn but unable to take part in CSG.
|
|
316
|
+
TEST(ImportModuleContext, AmfTriangleSoupWeldsIntoAClosedSolid) {
|
|
317
|
+
const Imported r = importText("soup.amf", soupAmf({cubeTris(0, 0, 0)}));
|
|
318
|
+
EXPECT_NEAR(r.volume, 1.0, 1e-9);
|
|
319
|
+
EXPECT_FALSE(anyContains(r.messages, "not a closed solid")) << ::testing::PrintToString(r.messages);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// A 3x3x1 slab with a 1x1 hole through it (eight unit cubes around the
|
|
323
|
+
// middle, the faces between neighbours left out), as a soup: closed, genus 1.
|
|
324
|
+
TEST(ImportModuleContext, AmfSoupWithAThroughHoleWeldsClosed) {
|
|
325
|
+
std::map<std::vector<std::array<double, 3>>, std::vector<Tri>> faces;
|
|
326
|
+
std::map<std::vector<std::array<double, 3>>, int> uses;
|
|
327
|
+
for (int i = 0; i < 3; ++i)
|
|
328
|
+
for (int j = 0; j < 3; ++j) {
|
|
329
|
+
if (i == 1 && j == 1) continue;
|
|
330
|
+
const std::vector<Tri> c = cubeTris(i, j, 0);
|
|
331
|
+
for (size_t f = 0; f < c.size(); f += 2) {
|
|
332
|
+
std::vector<std::array<double, 3>> key{c[f][0], c[f][1], c[f][2], c[f + 1][0], c[f + 1][1], c[f + 1][2]};
|
|
333
|
+
std::sort(key.begin(), key.end());
|
|
334
|
+
key.erase(std::unique(key.begin(), key.end()), key.end());
|
|
335
|
+
faces[key] = {c[f], c[f + 1]};
|
|
336
|
+
++uses[key];
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
std::vector<Tri> ring;
|
|
340
|
+
for (const auto& [key, tris] : faces)
|
|
341
|
+
if (uses[key] == 1) ring.insert(ring.end(), tris.begin(), tris.end());
|
|
342
|
+
const auto path = tempPath("ring.amf");
|
|
343
|
+
std::ofstream(path, std::ios::binary) << soupAmf({ring});
|
|
344
|
+
std::vector<std::string> messages;
|
|
345
|
+
Evaluated e = evalSrc("import(\"" + path.generic_string() + "\");",
|
|
346
|
+
[&](const std::string& m) { messages.push_back(m); });
|
|
347
|
+
std::filesystem::remove(path);
|
|
348
|
+
ASSERT_EQ(e.bodies.size(), 1u);
|
|
349
|
+
ASSERT_TRUE(e.bodies[0].body);
|
|
350
|
+
EXPECT_NEAR(e.bodies[0].body->Volume(), 8.0, 1e-9);
|
|
351
|
+
EXPECT_EQ(e.bodies[0].body->Genus(), 1);
|
|
352
|
+
EXPECT_FALSE(anyContains(messages, "not a closed solid")) << ::testing::PrintToString(messages);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// The weld is per object, as in OpenSCAD: a cube split into two objects,
|
|
356
|
+
// each half its triangles, is two open surfaces, not one closed cube.
|
|
357
|
+
TEST(ImportModuleContext, AmfWeldsWithinAnObjectOnly) {
|
|
358
|
+
const std::vector<Tri> c = cubeTris(0, 0, 0);
|
|
359
|
+
const Imported r = importText("halves.amf", soupAmf({{c.begin(), c.begin() + 6}, {c.begin() + 6, c.end()}}));
|
|
360
|
+
EXPECT_TRUE(anyContains(r.messages, "not a closed solid")) << ::testing::PrintToString(r.messages);
|
|
361
|
+
}
|
|
362
|
+
|
|
270
363
|
TEST(ImportModuleContext, UnsupportedExtensionErrors) {
|
|
271
364
|
const auto path = tempPath("unsupported.xyz");
|
|
272
365
|
std::ofstream(path) << "x";
|
|
File without changes
|
{openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/.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.45.0 → openscad_cpp_evaluator-1.45.2}/examples/eval_perf_benchmark.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/manifold_cache_reuse.cpp
RENAMED
|
File without changes
|
{openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/examples/minimal_debugger.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openscad_cpp_evaluator-1.45.0 → openscad_cpp_evaluator-1.45.2}/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
|