@bldrs-ai/conway 1.389.1221 → 1.394.1504
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.
- package/README.md +36 -22
- package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
- package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
- package/compiled/dependencies/conway-geom/interface/conway_geometry.js +17 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts +6 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts.map +1 -1
- package/compiled/examples/browser-bundled.cjs +1569 -51
- package/compiled/examples/cli-bundled.cjs +2790 -436
- package/compiled/examples/cli-step-bundled.cjs +1904 -229
- package/compiled/examples/validator-bundled.cjs +1569 -51
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.js +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/schema_ap214.gen.js +11 -11
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_command_line_main.js +7 -3
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +181 -7
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +906 -137
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +10 -2
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.js +114 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts +6 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_model_geometry.js +9 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.js +233 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.js +147 -0
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.js +65 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.js +111 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.js +190 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.js +110 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts +165 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.js +286 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.js +225 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +154 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +211 -3
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +288 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +39 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +30 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +83 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +383 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +132 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +488 -92
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +268 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +996 -149
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +129 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts +134 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.js +933 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.js +467 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +187 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.js +524 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.js +234 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +306 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.js +580 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.js +22 -0
- package/compiled/src/core/composed_model_skeleton.d.ts +63 -0
- package/compiled/src/core/composed_model_skeleton.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.js +66 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts +2 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.test.js +69 -0
- package/compiled/src/core/demand_geometry_queue.d.ts +147 -0
- package/compiled/src/core/demand_geometry_queue.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.js +223 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts +2 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.test.js +133 -0
- package/compiled/src/core/demand_residency_pump.d.ts +93 -0
- package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.js +120 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.test.js +148 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.js +76 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
- package/compiled/src/core/geometry_tile_pool.d.ts +99 -0
- package/compiled/src/core/geometry_tile_pool.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.js +104 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.test.js +180 -0
- package/compiled/src/core/mem/chunked_pool.d.ts +116 -0
- package/compiled/src/core/mem/chunked_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.js +149 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.test.js +63 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts +82 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.js +113 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.test.js +49 -0
- package/compiled/src/core/model_registry.d.ts +87 -0
- package/compiled/src/core/model_registry.d.ts.map +1 -0
- package/compiled/src/core/model_registry.js +101 -0
- package/compiled/src/core/model_registry.test.d.ts +2 -0
- package/compiled/src/core/model_registry.test.d.ts.map +1 -0
- package/compiled/src/core/model_registry.test.js +60 -0
- package/compiled/src/core/model_uri.d.ts +57 -0
- package/compiled/src/core/model_uri.d.ts.map +1 -0
- package/compiled/src/core/model_uri.js +101 -0
- package/compiled/src/core/model_uri.test.d.ts +2 -0
- package/compiled/src/core/model_uri.test.d.ts.map +1 -0
- package/compiled/src/core/model_uri.test.js +49 -0
- package/compiled/src/core/progress.d.ts +16 -2
- package/compiled/src/core/progress.d.ts.map +1 -1
- package/compiled/src/core/progress.js +31 -5
- package/compiled/src/core/progress.test.js +11 -2
- package/compiled/src/core/progress_log.d.ts +1 -0
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +7 -2
- package/compiled/src/core/progress_log.test.js +21 -0
- package/compiled/src/core/shared_byte_budget.d.ts +60 -0
- package/compiled/src/core/shared_byte_budget.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.js +85 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts +2 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.test.js +55 -0
- package/compiled/src/core/wasm_heap.d.ts +208 -0
- package/compiled/src/core/wasm_heap.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.js +417 -0
- package/compiled/src/core/wasm_heap.test.d.ts +2 -0
- package/compiled/src/core/wasm_heap.test.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.test.js +546 -0
- package/compiled/src/demand/index.d.ts +23 -0
- package/compiled/src/demand/index.d.ts.map +1 -0
- package/compiled/src/demand/index.js +22 -0
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.js +2 -2
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/schema_ifc.gen.js +2 -2
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.js +251 -0
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts +367 -6
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_geometry_extraction.js +1322 -389
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_grid_placement.test.js +261 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts +12 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_model_geometry.js +15 -0
- package/compiled/src/ifc/ifc_regression_batch_main.js +210 -12
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts +145 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.js +266 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.js +199 -0
- package/compiled/src/ifc/ifc_step_model.d.ts +6 -2
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +6 -4
- package/compiled/src/ifc/ifc_step_parser.d.ts +58 -0
- package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_parser.js +64 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
- package/compiled/src/ifc/ifc_stream_open.d.ts +131 -0
- package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.js +116 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.test.js +230 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.js +60 -0
- package/compiled/src/index.d.ts +21 -1
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +28 -1
- package/compiled/src/logging/logger.d.ts +16 -2
- package/compiled/src/logging/logger.d.ts.map +1 -1
- package/compiled/src/logging/logger.js +34 -7
- package/compiled/src/logging/logger.test.js +30 -0
- package/compiled/src/mem/index.d.ts +17 -0
- package/compiled/src/mem/index.d.ts.map +1 -0
- package/compiled/src/mem/index.js +16 -0
- package/compiled/src/namespace_surface.test.d.ts +2 -0
- package/compiled/src/namespace_surface.test.d.ts.map +1 -0
- package/compiled/src/namespace_surface.test.js +43 -0
- package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
- package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
- package/compiled/src/parsing/parsing_buffer.js +31 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts +2 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
- package/compiled/src/scripts/model_report_displacement.test.js +104 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts +2 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts.map +1 -0
- package/compiled/src/scripts/render_glb_paths.test.js +115 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
- package/compiled/src/step/indexing/step_type_indexer.js +67 -0
- package/compiled/src/step/parsing/byte_source.d.ts +153 -0
- package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.js +106 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.test.js +47 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts +41 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source_node.js +54 -0
- package/compiled/src/step/parsing/columnar_index.d.ts +103 -0
- package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.js +224 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.test.js +155 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts +95 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.js +91 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts +2 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.js +66 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
- package/compiled/src/step/parsing/decode_utf8.js +28 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts +20 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.js +91 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts +2 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.test.js +28 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts +81 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.js +283 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts +2 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.test.js +122 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.js +108 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts +124 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.js +207 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.test.js +298 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts +69 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.js +78 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.test.js +70 -0
- package/compiled/src/step/parsing/record_event.d.ts +23 -0
- package/compiled/src/step/parsing/record_event.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_event.js +1 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts +94 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_field_cursor.js +189 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts +29 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_deserialization_functions.js +45 -0
- package/compiled/src/step/parsing/step_deserialization_functions.test.js +59 -1
- package/compiled/src/step/parsing/step_parser.d.ts +66 -1
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +164 -10
- package/compiled/src/step/parsing/step_string_parser.js +8 -8
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +141 -0
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.js +280 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.js +109 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +71 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.js +88 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
- package/compiled/src/step/parsing/uint32_sink.d.ts +72 -0
- package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.js +180 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.test.js +199 -0
- package/compiled/src/step/step_buffer_provider.d.ts +48 -3
- package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
- package/compiled/src/step/step_buffer_provider.js +60 -11
- package/compiled/src/step/step_buffer_provider.test.js +14 -0
- package/compiled/src/step/step_entity_base.d.ts +65 -3
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +135 -3
- package/compiled/src/step/step_model_base.d.ts +221 -8
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +542 -7
- package/compiled/src/stream/index.d.ts +34 -0
- package/compiled/src/stream/index.d.ts.map +1 -0
- package/compiled/src/stream/index.js +32 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -1
|
@@ -1,21 +1,65 @@
|
|
|
1
1
|
import { ConwayGeometry, } from "../../index.js";
|
|
2
|
+
import IfcStepModel from "../../ifc/ifc_step_model.js";
|
|
3
|
+
import { WindowedStepBufferProvider } from "../../step/step_buffer_provider.js";
|
|
2
4
|
import * as glmatrix from "gl-matrix";
|
|
5
|
+
import { IDENTITY_MAT4, LARGE_COORDINATE_BUDGET_M, TRANSLATION_X, TRANSLATION_Y, TRANSLATION_Z, composeTransformF64, deriveCoordinationF64 } from "./coordination_f64.js";
|
|
3
6
|
import { IfcProperties } from "./ifc_properties.js";
|
|
4
7
|
import Logger from "../../logging/logger.js";
|
|
5
8
|
import { ProgressTracker } from "../../core/progress.js";
|
|
6
9
|
import { formatModelLine } from "../../core/progress_log.js";
|
|
10
|
+
import { wasmHeapView, } from "../../core/wasm_heap.js";
|
|
7
11
|
import { extractModelInfo } from "../../loaders/loading_utilities.js";
|
|
8
12
|
import IfcStepParser from "../../ifc/ifc_step_parser.js";
|
|
9
13
|
import ParsingBuffer from "../../parsing/parsing_buffer.js";
|
|
14
|
+
import { BufferByteSource, StoreByteSource } from "../../step/parsing/byte_source.js";
|
|
15
|
+
import { buildIndexStreamingAsync, } from "../../step/parsing/streaming_index_builder.js";
|
|
16
|
+
import { ColumnarIndexSink } from "../../step/parsing/columnar_index.js";
|
|
17
|
+
import { StorePreviewChannel } from "./store_preview_channel.js";
|
|
18
|
+
import { ifcPreviewAdapter, StreamedPreviewChannel, } from "./streamed_preview_channel.js";
|
|
19
|
+
import { emitSpatialStructureImposters } from "./spatial_imposter.js";
|
|
10
20
|
import { ExtractResult } from "../../index.js";
|
|
11
21
|
import { IfcGeometryExtraction } from "../../ifc/ifc_geometry_extraction.js";
|
|
12
22
|
import { ParseResult } from "../../index.js";
|
|
23
|
+
import { releaseScratchParsingBuffer } from "../../step/parsing/step_deserialization_functions.js";
|
|
13
24
|
import Memory from "../../memory/memory.js";
|
|
14
25
|
import { FromRawLineData } from "./ifc2x4_helper.js";
|
|
15
26
|
import { shimIfcEntityMap, shimIfcEntityReverseMap } from "./shim_schema_mapping.js";
|
|
16
27
|
import { EntityTypesIfcCount } from "../../ifc/ifc4_gen/entity_types_ifc.gen.js";
|
|
17
|
-
import { IfcProduct, IfcRoot } from "../../ifc/ifc4_gen/index.js";
|
|
28
|
+
import { IfcProduct, IfcRelAggregates, IfcRoot } from "../../ifc/ifc4_gen/index.js";
|
|
18
29
|
import { CanonicalMeshType } from "../../index.js";
|
|
30
|
+
// Batch size used when a whole-model consumer (streamAllMeshes) drains
|
|
31
|
+
// a deferred model's remaining products synchronously.
|
|
32
|
+
const DEFERRED_DRAIN_BATCH = 256;
|
|
33
|
+
/* Moving-window size for the streamed columnar parse (matches the
|
|
34
|
+
* ifc_stream_open default; the window bounds parse-time scratch, not
|
|
35
|
+
* the source buffer, which the model keeps resident here). */
|
|
36
|
+
// eslint-disable-next-line no-magic-numbers
|
|
37
|
+
const STREAMED_PARSE_POOL_BYTES = 1024 * 1024;
|
|
38
|
+
/* Store-backed open pays an await per window slide (`File.slice`).
|
|
39
|
+
* 1 MiB on an 860 MB IFC is ~1700 trips; 16 MiB is ~100. The window
|
|
40
|
+
* is scratch — it does not stay resident after parse. */
|
|
41
|
+
// eslint-disable-next-line no-magic-numbers
|
|
42
|
+
const STORE_PARSE_POOL_BYTES = 16 * 1024 * 1024;
|
|
43
|
+
// eslint-disable-next-line no-magic-numbers
|
|
44
|
+
const BYTES_PER_MIB = 1024 * 1024;
|
|
45
|
+
/**
|
|
46
|
+
* The coordination frame spatial-structure imposters compose under.
|
|
47
|
+
*
|
|
48
|
+
* With COORDINATE_TO_ORIGIN on, that is whatever frame the preview
|
|
49
|
+
* channel latched (undefined when it never captured an instance — the
|
|
50
|
+
* imposter walk then derives an equivalent one itself). With it OFF the
|
|
51
|
+
* durable capture composes against a bare identity, so the plates must
|
|
52
|
+
* too, or they would be the only thing in the scene in metres and Y-up.
|
|
53
|
+
*
|
|
54
|
+
* @param settings The open's loader settings.
|
|
55
|
+
* @param previewCoordination The preview channel's latched frame.
|
|
56
|
+
* @return {ArrayLike<number> | undefined} The frame, or undefined to let
|
|
57
|
+
* the imposter walk derive one.
|
|
58
|
+
*/
|
|
59
|
+
function imposterCoordination(settings, previewCoordination) {
|
|
60
|
+
return settings?.COORDINATE_TO_ORIGIN === true ?
|
|
61
|
+
previewCoordination : IDENTITY_MAT4;
|
|
62
|
+
}
|
|
19
63
|
/**
|
|
20
64
|
* The proxy for IFC from the shim.
|
|
21
65
|
*/
|
|
@@ -31,6 +75,44 @@ export class IfcApiProxyIfc {
|
|
|
31
75
|
this.wasmModule = wasmModule;
|
|
32
76
|
this.settings = settings;
|
|
33
77
|
this.fs = undefined;
|
|
78
|
+
/** Was this model opened without extraction (DEFER_GEOMETRY)? */
|
|
79
|
+
this.deferredMode_ = false;
|
|
80
|
+
/** True once beginPhase('geometry') has fired for this deferred pump. */
|
|
81
|
+
this.geometryPhaseStarted_ = false;
|
|
82
|
+
/**
|
|
83
|
+
* Deferred capture watermarks: entity localID -> how many of its
|
|
84
|
+
* placed instances (in scene-walk order) have been captured. Shared
|
|
85
|
+
* (mapped) geometry attributes instances to an entity from OTHER
|
|
86
|
+
* products' extractions, so an entity's instance set grows across
|
|
87
|
+
* batches - the watermark makes each instance captured exactly once,
|
|
88
|
+
* in the same order the classic single walk would process it.
|
|
89
|
+
*/
|
|
90
|
+
this.demandCapturedCounts_ = new Map();
|
|
91
|
+
/** Cursor into demandProducts_ — products before it are extracted. */
|
|
92
|
+
this.demandCursor_ = 0;
|
|
93
|
+
/** Wall-clock split of the store-backed batch pump (profile script). */
|
|
94
|
+
this.extractProfile_ = {
|
|
95
|
+
prefetchMs: 0,
|
|
96
|
+
extractMs: 0,
|
|
97
|
+
releaseMs: 0,
|
|
98
|
+
batches: 0,
|
|
99
|
+
lastPins: 0,
|
|
100
|
+
pinMax: 0,
|
|
101
|
+
};
|
|
102
|
+
/** Cursor into demandAggregates_ — items before it are extracted. */
|
|
103
|
+
this.demandAggregatesCursor_ = 0;
|
|
104
|
+
/**
|
|
105
|
+
* True while an adopted preview-channel coordination frame is still
|
|
106
|
+
* unvalidated against the durable walk's first geometry. A model can
|
|
107
|
+
* carry geometry in more than one frame (ISSUE_129: a local-scale
|
|
108
|
+
* annotation previews first while the body is georeferenced at
|
|
109
|
+
* ~8.3e6 m), so a frame anchored on the wrong unit leaves the body
|
|
110
|
+
* raw — the Share#1634 browser-vs-node divergence, which was really
|
|
111
|
+
* preview-vs-no-preview. streamNewMeshes_ clears this on its first
|
|
112
|
+
* geometry, re-deriving from it when the adopted frame fails the
|
|
113
|
+
* large-coordinate budget.
|
|
114
|
+
*/
|
|
115
|
+
this.demandCoordinationFromPreview_ = false;
|
|
34
116
|
this._isCoordinated = false;
|
|
35
117
|
this.linearScalingFactor = 1;
|
|
36
118
|
this.identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
@@ -43,12 +125,18 @@ export class IfcApiProxyIfc {
|
|
|
43
125
|
* Contains all the logic and methods regarding properties, psets, qsets, etc.
|
|
44
126
|
*/
|
|
45
127
|
this.properties = new IfcProperties(this);
|
|
128
|
+
/** Native geometry freed (releaseGeometry) — scene walks would touch
|
|
129
|
+
* freed objects, so mesh serving degrades to the accumulated maps. */
|
|
130
|
+
this.released_ = false;
|
|
46
131
|
// The cooperative path (createAsync) parses/extracts before construction
|
|
47
132
|
// so it can await mid-load; the classic OpenModel path does it here,
|
|
48
133
|
// synchronously. Both share the tail below (mesh vectors, statistics).
|
|
49
134
|
const loadState = precomputed ??
|
|
50
135
|
IfcApiProxyIfc.parseAndExtract(modelID, data, new ConwayGeometry(wasmModule), settings);
|
|
51
136
|
this.conwaywasm = loadState.conwaywasm;
|
|
137
|
+
this.conwayGeometry_ = loadState.conwayGeometry;
|
|
138
|
+
this.deferredMode_ = loadState.deferred === true;
|
|
139
|
+
this.progressTracker_ = loadState.tracker;
|
|
52
140
|
const statistics = Logger.getStatistics(modelID);
|
|
53
141
|
const { allTimeStart, stepHeader, model, scene, conwayGeometry, geometryTimeInMs: executionTimeInMs, } = loadState;
|
|
54
142
|
// get linear scaling factor
|
|
@@ -124,6 +212,18 @@ export class IfcApiProxyIfc {
|
|
|
124
212
|
];
|
|
125
213
|
// save settings
|
|
126
214
|
this.settings = settings;
|
|
215
|
+
// Deferred opens whose preview channel already established the
|
|
216
|
+
// coordination frame: adopt it, so the durable capture skips its own
|
|
217
|
+
// derivation and places exactly where the preview did. (Internal
|
|
218
|
+
// only — getCoordinationMatrix stays identity, see
|
|
219
|
+
// demandCoordination_.)
|
|
220
|
+
if (this.deferredMode_ && loadState.previewCoordinationMatrix !== void 0) {
|
|
221
|
+
this.demandCoordination_ = loadState.previewCoordinationMatrix;
|
|
222
|
+
this._isCoordinated = true;
|
|
223
|
+
// Adopted, not derived: validate against the durable walk's first
|
|
224
|
+
// geometry before trusting it (see demandCoordinationFromPreview_).
|
|
225
|
+
this.demandCoordinationFromPreview_ = true;
|
|
226
|
+
}
|
|
127
227
|
let FILE_NAME = stepHeader.headers.get("FILE_NAME");
|
|
128
228
|
if (FILE_NAME !== void 0) {
|
|
129
229
|
// strip start / end parenthesis
|
|
@@ -167,6 +267,62 @@ export class IfcApiProxyIfc {
|
|
|
167
267
|
const loadState = await IfcApiProxyIfc.parseAndExtractAsync(modelID, data, new ConwayGeometry(wasmModule), settings);
|
|
168
268
|
return new IfcApiProxyIfc(modelID, data, wasmModule, settings, loadState);
|
|
169
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Streamed-open construction (conway extension, used by
|
|
272
|
+
* OpenModelStreamed): the parse runs through the streaming columnar
|
|
273
|
+
* indexer, so the model's index is columnar from birth and the
|
|
274
|
+
* per-record object phase — the dominant JS-heap cost of the classic
|
|
275
|
+
* parse on large models — never exists. Geometry extraction is the
|
|
276
|
+
* same cooperative path OpenModelAsync uses, and everything
|
|
277
|
+
* downstream (meshes, properties, SpillModelSource) behaves
|
|
278
|
+
* identically to a classic open.
|
|
279
|
+
*
|
|
280
|
+
* @param modelID The model ID being opened.
|
|
281
|
+
* @param data The IFC data buffer.
|
|
282
|
+
* @param wasmModule The wasm module.
|
|
283
|
+
* @param settings Loader settings (ON_PROGRESS is honored).
|
|
284
|
+
* @return {Promise<IfcApiProxyIfc>} The constructed proxy.
|
|
285
|
+
*/
|
|
286
|
+
static async createStreamed(modelID, data, wasmModule, settings) {
|
|
287
|
+
const loadState = await IfcApiProxyIfc.parseColumnarAndExtractAsync(modelID, data, new ConwayGeometry(wasmModule), settings);
|
|
288
|
+
return new IfcApiProxyIfc(modelID, data, wasmModule, settings, loadState);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Deferred-geometry streamed open (conway extension; slice A of
|
|
292
|
+
* Share's demand/tiled rendering — design doc
|
|
293
|
+
* demand-tiled-rendering.md): identical streamed columnar parse, but
|
|
294
|
+
* NO geometry extraction happens at open. The proxy registers with an
|
|
295
|
+
* empty scene wired to the demand-extraction seam; callers then pump
|
|
296
|
+
* {@link extractGeometryBatch} to extract products in file-order
|
|
297
|
+
* batches, receiving each batch's meshes incrementally — the scene,
|
|
298
|
+
* properties, and spatial structure work from the first batch.
|
|
299
|
+
*
|
|
300
|
+
* @param modelID The model ID being opened.
|
|
301
|
+
* @param data The IFC data buffer.
|
|
302
|
+
* @param wasmModule The wasm module.
|
|
303
|
+
* @param settings Loader settings (ON_PROGRESS is honored for parse).
|
|
304
|
+
* @return {Promise<IfcApiProxyIfc>} The constructed proxy.
|
|
305
|
+
*/
|
|
306
|
+
static async createDeferred(modelID, data, wasmModule, settings) {
|
|
307
|
+
const loadState = await IfcApiProxyIfc.parseColumnarAndExtractAsync(modelID, data, new ConwayGeometry(wasmModule), settings, true);
|
|
308
|
+
return new IfcApiProxyIfc(modelID, data, wasmModule, settings, loadState);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* M1b store-backed open: parse through a moving window over `store`
|
|
312
|
+
* and keep the model windowed from birth — the source is never held
|
|
313
|
+
* as one `ArrayBuffer`. Geometry extract pages product closures
|
|
314
|
+
* through {@link extractGeometryBatchAsync}.
|
|
315
|
+
*
|
|
316
|
+
* @param modelID The model ID being opened.
|
|
317
|
+
* @param store External store holding the source bytes.
|
|
318
|
+
* @param wasmModule The wasm module.
|
|
319
|
+
* @param settings Loader settings (ON_PROGRESS is honored).
|
|
320
|
+
* @return {Promise<IfcApiProxyIfc>} The constructed proxy.
|
|
321
|
+
*/
|
|
322
|
+
static async createFromStore(modelID, store, wasmModule, settings) {
|
|
323
|
+
const loadState = await IfcApiProxyIfc.parseColumnarFromStore(modelID, store, new ConwayGeometry(wasmModule), settings, settings?.DEFER_GEOMETRY === true);
|
|
324
|
+
return new IfcApiProxyIfc(modelID, new Uint8Array(0), wasmModule, settings, loadState);
|
|
325
|
+
}
|
|
170
326
|
/**
|
|
171
327
|
* Log + record the header parse result on the model statistics.
|
|
172
328
|
*
|
|
@@ -342,6 +498,334 @@ export class IfcApiProxyIfc {
|
|
|
342
498
|
geometryTimeInMs: endTime - startTime,
|
|
343
499
|
};
|
|
344
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* Streamed twin of parseAndExtractAsync: the data parse runs through
|
|
503
|
+
* the streaming columnar indexer over a moving window instead of the
|
|
504
|
+
* per-record object parse, so the index is columnar from birth (no
|
|
505
|
+
* object phase). The source buffer stays resident behind the model —
|
|
506
|
+
* extraction and synchronous property reads behave exactly like a
|
|
507
|
+
* classic open, and `spillSourceToExternalStore` works afterwards as
|
|
508
|
+
* usual.
|
|
509
|
+
*
|
|
510
|
+
* The columnar build is cooperative (periodic event-loop yields, like
|
|
511
|
+
* the classic parseDataBlockAsync) with absolute byte-cursor progress
|
|
512
|
+
* ticks, and extraction is cooperative too — the streamed open keeps
|
|
513
|
+
* the repaint/no-stall property of OpenModelAsync (#301 §2). Throws
|
|
514
|
+
* when the streamed parse is anything but COMPLETE — the caller
|
|
515
|
+
* (OpenModelStreamed) falls back to the classic path, which tolerates
|
|
516
|
+
* recoverable parses.
|
|
517
|
+
*
|
|
518
|
+
* @param modelID The model ID being opened.
|
|
519
|
+
* @param data The IFC data buffer.
|
|
520
|
+
* @param conwaywasm The conway geometry wasm wrapper.
|
|
521
|
+
* @param settings Loader settings (ON_PROGRESS is honored).
|
|
522
|
+
* @return {Promise<IfcProxyLoadState>} Everything the constructor tail needs.
|
|
523
|
+
*/
|
|
524
|
+
static async parseColumnarAndExtractAsync(modelID, data, conwaywasm, settings, deferGeometry = false) {
|
|
525
|
+
const tracker = IfcApiProxyIfc.makeTracker(settings);
|
|
526
|
+
const allTimeStart = Date.now();
|
|
527
|
+
const parser = IfcStepParser.Instance;
|
|
528
|
+
const bufferInput = new ParsingBuffer(data);
|
|
529
|
+
tracker?.beginPhase("headerParse", "bytes", data.length);
|
|
530
|
+
// Header parsed standalone first so the model line fires before the
|
|
531
|
+
// full parse, exactly like the classic path (the columnar build
|
|
532
|
+
// re-reads the tiny header internally; the cost is negligible).
|
|
533
|
+
const [stepHeader, result0] = parser.parseHeader(bufferInput);
|
|
534
|
+
Logger.createStatistics(modelID);
|
|
535
|
+
const statistics = Logger.getStatistics(modelID);
|
|
536
|
+
IfcApiProxyIfc.reportHeaderParseResult(result0, bufferInput, modelID);
|
|
537
|
+
const modelInfo = extractModelInfo(stepHeader, data.length);
|
|
538
|
+
Logger.info(formatModelLine(modelInfo));
|
|
539
|
+
settings?.ON_MODEL_INFO?.(modelInfo);
|
|
540
|
+
tracker?.beginPhase("dataParse", "bytes", data.length);
|
|
541
|
+
const parseTick = tracker !== void 0 ?
|
|
542
|
+
(cursorBytes) => tracker.update(cursorBytes) : void 0;
|
|
543
|
+
const parseStartTime = Date.now();
|
|
544
|
+
// Inline twin of buildColumnarIndexStreamingAsync — the sink is created
|
|
545
|
+
// here so the parse-time preview channel (slice A2) can watch it grow
|
|
546
|
+
// and snapshot prefix models between the parse's cooperative yields.
|
|
547
|
+
const sink = new ColumnarIndexSink();
|
|
548
|
+
const previewChannel = deferGeometry && settings?.ON_PREVIEW_MESH !== void 0 ?
|
|
549
|
+
new StreamedPreviewChannel(data, conwaywasm, sink, ifcPreviewAdapter(), settings.COORDINATE_TO_ORIGIN === true, settings.ON_PREVIEW_MESH) : void 0;
|
|
550
|
+
previewChannel?.start();
|
|
551
|
+
// Channel ticks ride the parse's own progress callback (see
|
|
552
|
+
// maybeTickInline) — timer ticks alone starve under the parse's
|
|
553
|
+
// scheduler-priority yields in browsers.
|
|
554
|
+
const parseProgress = previewChannel !== void 0 ?
|
|
555
|
+
(cursorBytes) => {
|
|
556
|
+
parseTick?.(cursorBytes);
|
|
557
|
+
previewChannel.maybeTickInline();
|
|
558
|
+
} : parseTick;
|
|
559
|
+
let result;
|
|
560
|
+
try {
|
|
561
|
+
({ result } = await buildIndexStreamingAsync(new BufferByteSource(data), parser, STREAMED_PARSE_POOL_BYTES, void 0, sink, parseProgress));
|
|
562
|
+
}
|
|
563
|
+
finally {
|
|
564
|
+
previewChannel?.stop();
|
|
565
|
+
}
|
|
566
|
+
const columns = sink.finalize();
|
|
567
|
+
const parseEndTime = Date.now();
|
|
568
|
+
tracker?.endPhase(data.length);
|
|
569
|
+
if (result !== ParseResult.COMPLETE) {
|
|
570
|
+
Logger.warning(`[OpenModelStreamed]: streamed parse result ${result}`);
|
|
571
|
+
statistics?.setLoadStatus("PARSE_FAIL");
|
|
572
|
+
throw new Error("Streamed parse did not complete");
|
|
573
|
+
}
|
|
574
|
+
const model = new IfcStepModel(data, columns);
|
|
575
|
+
statistics?.setParseTime(parseEndTime - parseStartTime);
|
|
576
|
+
const conwayGeometry = new IfcGeometryExtraction(conwaywasm, model);
|
|
577
|
+
// Deferred mode (createDeferred): no extraction now — prime the
|
|
578
|
+
// per-product demand seam and hand back the (empty) live scene the
|
|
579
|
+
// batch pump populates. `scene` is the same object streamAllMeshes
|
|
580
|
+
// walks, so meshes appear to consumers as batches extract.
|
|
581
|
+
if (deferGeometry) {
|
|
582
|
+
conwayGeometry.prepareDemandExtraction();
|
|
583
|
+
if (settings?.ON_PREVIEW_MESH !== void 0) {
|
|
584
|
+
try {
|
|
585
|
+
// After prepareDemandExtraction, not before: the plates are
|
|
586
|
+
// composed under the coordination frame, whose scaling comes
|
|
587
|
+
// from getLinearScalingFactor() — which reads 1 until the
|
|
588
|
+
// extraction maps (and with them the unit assignment) are
|
|
589
|
+
// prepared. Both calls run in the same synchronous stretch
|
|
590
|
+
// after the parse, so nothing reaches the screen any later.
|
|
591
|
+
await emitSpatialStructureImposters(model, settings.ON_PREVIEW_MESH, imposterCoordination(settings, previewChannel?.coordinationMatrix), conwayGeometry.getLinearScalingFactor());
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
// Spatial imposters must never break a deferred open.
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
statistics?.setProductCount(model.typeCount(IfcProduct));
|
|
598
|
+
return {
|
|
599
|
+
conwaywasm,
|
|
600
|
+
deferred: true,
|
|
601
|
+
// Pin the durable pump's coordination to the preview channel's
|
|
602
|
+
// (derived from the same first instance with the same math), so
|
|
603
|
+
// preview payloads and durable meshes share one frame.
|
|
604
|
+
previewCoordinationMatrix: previewChannel?.coordinationMatrix,
|
|
605
|
+
allTimeStart,
|
|
606
|
+
stepHeader,
|
|
607
|
+
model,
|
|
608
|
+
scene: conwayGeometry.scene,
|
|
609
|
+
conwayGeometry,
|
|
610
|
+
geometryTimeInMs: 0,
|
|
611
|
+
tracker,
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
tracker?.beginPhase("geometry", "products");
|
|
615
|
+
const geometryTick = tracker !== void 0 ?
|
|
616
|
+
(completed, total) => {
|
|
617
|
+
tracker.setPhaseTotal(total);
|
|
618
|
+
tracker.update(completed);
|
|
619
|
+
} : void 0;
|
|
620
|
+
const startTime = Date.now();
|
|
621
|
+
const [extractionResult, scene] = await conwayGeometry.extractIFCGeometryDataAsync(geometryTick);
|
|
622
|
+
const endTime = Date.now();
|
|
623
|
+
tracker?.endPhase();
|
|
624
|
+
if (extractionResult !== ExtractResult.COMPLETE) {
|
|
625
|
+
Logger.error("[OpenModelStreamed]: Error extracting geometry, exiting...");
|
|
626
|
+
statistics?.setLoadStatus("FAIL");
|
|
627
|
+
throw new Error("Couldn't extract model");
|
|
628
|
+
}
|
|
629
|
+
statistics?.setProductCount(model.typeCount(IfcProduct));
|
|
630
|
+
statistics?.setGeometryTypeCounts(conwayGeometry.geometryTypeCounts);
|
|
631
|
+
return {
|
|
632
|
+
conwaywasm,
|
|
633
|
+
allTimeStart,
|
|
634
|
+
stepHeader,
|
|
635
|
+
model,
|
|
636
|
+
scene,
|
|
637
|
+
conwayGeometry,
|
|
638
|
+
geometryTimeInMs: endTime - startTime,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Windowed-from-birth twin of parseColumnarAndExtractAsync: the
|
|
643
|
+
* source stays in `store`, parse windows are filled through it, and
|
|
644
|
+
* the model never holds a resident copy. During parse a bounded
|
|
645
|
+
* prefix extract pages product closures from the store and emits
|
|
646
|
+
* placed meshes (same COORDINATE_TO_ORIGIN frame as durable). After
|
|
647
|
+
* the index exists, spatial-structure AABB plates go out too.
|
|
648
|
+
* Deferred opens page prep closures before prepareDemandExtraction;
|
|
649
|
+
* non-deferred opens drain the demand pump with per-product residency.
|
|
650
|
+
*
|
|
651
|
+
* @param modelID The model ID being opened.
|
|
652
|
+
* @param store External store holding the source bytes.
|
|
653
|
+
* @param conwaywasm The conway geometry wasm wrapper.
|
|
654
|
+
* @param settings Loader settings (ON_PROGRESS is honored).
|
|
655
|
+
* @param deferGeometry Skip extraction (Share demand pump).
|
|
656
|
+
* @return {Promise<IfcProxyLoadState>} Everything the constructor tail needs.
|
|
657
|
+
*/
|
|
658
|
+
static async parseColumnarFromStore(modelID, store, conwaywasm, settings, deferGeometry = false) {
|
|
659
|
+
const tracker = IfcApiProxyIfc.makeTracker(settings);
|
|
660
|
+
const allTimeStart = Date.now();
|
|
661
|
+
const parser = IfcStepParser.Instance;
|
|
662
|
+
const fileSize = store.byteLength;
|
|
663
|
+
Logger.createStatistics(modelID);
|
|
664
|
+
const statistics = Logger.getStatistics(modelID);
|
|
665
|
+
tracker?.beginPhase("dataParse", "bytes", fileSize);
|
|
666
|
+
const parseTick = tracker !== void 0 ?
|
|
667
|
+
(cursorBytes) => tracker.update(cursorBytes) : void 0;
|
|
668
|
+
const parseStartTime = Date.now();
|
|
669
|
+
// Live sink so the store preview channel can snapshot a prefix
|
|
670
|
+
// mid-parse without a resident source buffer.
|
|
671
|
+
const sink = new ColumnarIndexSink();
|
|
672
|
+
const storePreview = settings?.ON_PREVIEW_MESH !== void 0 ?
|
|
673
|
+
new StorePreviewChannel(store, sink, conwaywasm, settings.COORDINATE_TO_ORIGIN === true, settings.ON_PREVIEW_MESH) : void 0;
|
|
674
|
+
const parseProgress = async (cursorBytes) => {
|
|
675
|
+
parseTick?.(cursorBytes);
|
|
676
|
+
await storePreview?.maybeTickAsync();
|
|
677
|
+
};
|
|
678
|
+
// One windowed pass: header comes out of the same slide as the
|
|
679
|
+
// data block so we do not hold a second 16 MiB prefix copy.
|
|
680
|
+
let result;
|
|
681
|
+
let stepHeader;
|
|
682
|
+
try {
|
|
683
|
+
({ result, header: stepHeader } = await buildIndexStreamingAsync(new StoreByteSource(store), parser, STORE_PARSE_POOL_BYTES, void 0, sink, parseProgress));
|
|
684
|
+
if (storePreview !== void 0) {
|
|
685
|
+
await storePreview.flushAsync();
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
finally {
|
|
689
|
+
storePreview?.stop();
|
|
690
|
+
}
|
|
691
|
+
const columns = sink.finalize();
|
|
692
|
+
// Parse window is out of scope; drop the module scratch in case a
|
|
693
|
+
// numeric read during the slide left it pointed at that 16 MiB view.
|
|
694
|
+
releaseScratchParsingBuffer();
|
|
695
|
+
IfcApiProxyIfc.reportHeaderParseResult(result, new ParsingBuffer(new Uint8Array(0)), modelID);
|
|
696
|
+
const modelInfo = extractModelInfo(stepHeader, fileSize);
|
|
697
|
+
Logger.info(formatModelLine(modelInfo));
|
|
698
|
+
settings?.ON_MODEL_INFO?.(modelInfo);
|
|
699
|
+
const parseEndTime = Date.now();
|
|
700
|
+
tracker?.endPhase(fileSize);
|
|
701
|
+
if (result !== ParseResult.COMPLETE) {
|
|
702
|
+
Logger.warning(`[OpenModelStream]: streamed parse result ${result}`);
|
|
703
|
+
statistics?.setLoadStatus("PARSE_FAIL");
|
|
704
|
+
throw new Error("Streamed parse did not complete");
|
|
705
|
+
}
|
|
706
|
+
const provider = new WindowedStepBufferProvider(store);
|
|
707
|
+
const model = new IfcStepModel(void 0, columns, provider);
|
|
708
|
+
statistics?.setParseTime(parseEndTime - parseStartTime);
|
|
709
|
+
const conwayGeometry = new IfcGeometryExtraction(conwaywasm, model);
|
|
710
|
+
const prepPins = await conwayGeometry.ensureResidentForDemandPrep();
|
|
711
|
+
try {
|
|
712
|
+
conwayGeometry.prepareDemandExtraction();
|
|
713
|
+
}
|
|
714
|
+
finally {
|
|
715
|
+
model.releaseSourceViews(prepPins);
|
|
716
|
+
model.unpinLocalIDs(prepPins);
|
|
717
|
+
}
|
|
718
|
+
if (settings?.ON_PREVIEW_MESH !== void 0) {
|
|
719
|
+
try {
|
|
720
|
+
// Emitted after demand prep so getLinearScalingFactor() reports
|
|
721
|
+
// the model's real units — see the resident path's note.
|
|
722
|
+
await emitSpatialStructureImposters(model, settings.ON_PREVIEW_MESH, imposterCoordination(settings, storePreview?.coordinationMatrix), conwayGeometry.getLinearScalingFactor());
|
|
723
|
+
}
|
|
724
|
+
catch {
|
|
725
|
+
// Spatial imposters must never break a store-backed open.
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (deferGeometry) {
|
|
729
|
+
statistics?.setProductCount(model.typeCount(IfcProduct));
|
|
730
|
+
return {
|
|
731
|
+
conwaywasm,
|
|
732
|
+
deferred: true,
|
|
733
|
+
previewCoordinationMatrix: storePreview?.coordinationMatrix,
|
|
734
|
+
allTimeStart,
|
|
735
|
+
stepHeader,
|
|
736
|
+
model,
|
|
737
|
+
scene: conwayGeometry.scene,
|
|
738
|
+
conwayGeometry,
|
|
739
|
+
geometryTimeInMs: 0,
|
|
740
|
+
tracker,
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
tracker?.beginPhase("geometry", "products");
|
|
744
|
+
const startTime = Date.now();
|
|
745
|
+
const aggregateTargets = conwayGeometry.aggregateTargetLocalIDs();
|
|
746
|
+
let completed = 0;
|
|
747
|
+
tracker?.setPhaseTotal(model.typeCount(IfcProduct));
|
|
748
|
+
// eslint-disable-next-line no-magic-numbers
|
|
749
|
+
const EXTRACT_BATCH = 8;
|
|
750
|
+
const pending = [];
|
|
751
|
+
const flushProductBatch = async () => {
|
|
752
|
+
if (pending.length === 0) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const pins = new Set();
|
|
756
|
+
const leafSpans = [];
|
|
757
|
+
try {
|
|
758
|
+
await Promise.all(pending.map((localID) => conwayGeometry.ensureResidentForProductExtract(localID, pins, leafSpans)));
|
|
759
|
+
for (const localID of pending) {
|
|
760
|
+
try {
|
|
761
|
+
conwayGeometry.extractProductGeometryByLocalID(localID);
|
|
762
|
+
}
|
|
763
|
+
catch (error) {
|
|
764
|
+
Logger.error(`Error extracting product localID ${localID}: ` +
|
|
765
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
766
|
+
}
|
|
767
|
+
model.releaseSourceViews(pins);
|
|
768
|
+
++completed;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
finally {
|
|
772
|
+
model.releaseSourceViews(pins);
|
|
773
|
+
model.unpinLocalIDs(pins);
|
|
774
|
+
for (const span of leafSpans) {
|
|
775
|
+
model.unpinAddressRange(span.address, span.length);
|
|
776
|
+
}
|
|
777
|
+
pending.length = 0;
|
|
778
|
+
}
|
|
779
|
+
tracker?.update(completed, {
|
|
780
|
+
residentSourceMb: model.residentSourceBytes / BYTES_PER_MIB,
|
|
781
|
+
});
|
|
782
|
+
};
|
|
783
|
+
for (const product of model.types(IfcProduct)) {
|
|
784
|
+
if (aggregateTargets.has(product.localID)) {
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
pending.push(product.localID);
|
|
788
|
+
if (pending.length >= EXTRACT_BATCH) {
|
|
789
|
+
await flushProductBatch();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
await flushProductBatch();
|
|
793
|
+
for (const relAggregate of model.types(IfcRelAggregates)) {
|
|
794
|
+
const leafSpans = [];
|
|
795
|
+
const pins = await conwayGeometry.ensureResidentForAggregateExtract(relAggregate, leafSpans);
|
|
796
|
+
try {
|
|
797
|
+
conwayGeometry.extractRelAggregateGeometry(relAggregate);
|
|
798
|
+
}
|
|
799
|
+
catch (error) {
|
|
800
|
+
Logger.error(`Error extracting aggregate ${relAggregate.expressID}: ` +
|
|
801
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
802
|
+
}
|
|
803
|
+
finally {
|
|
804
|
+
model.releaseSourceViews(pins);
|
|
805
|
+
model.unpinLocalIDs(pins);
|
|
806
|
+
for (const span of leafSpans) {
|
|
807
|
+
model.unpinAddressRange(span.address, span.length);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
++completed;
|
|
811
|
+
tracker?.update(completed, {
|
|
812
|
+
residentSourceMb: model.residentSourceBytes / BYTES_PER_MIB,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
const endTime = Date.now();
|
|
816
|
+
tracker?.endPhase();
|
|
817
|
+
statistics?.setProductCount(model.typeCount(IfcProduct));
|
|
818
|
+
statistics?.setGeometryTypeCounts(conwayGeometry.geometryTypeCounts);
|
|
819
|
+
return {
|
|
820
|
+
conwaywasm,
|
|
821
|
+
allTimeStart,
|
|
822
|
+
stepHeader,
|
|
823
|
+
model,
|
|
824
|
+
scene: conwayGeometry.scene,
|
|
825
|
+
conwayGeometry,
|
|
826
|
+
geometryTimeInMs: endTime - startTime,
|
|
827
|
+
};
|
|
828
|
+
}
|
|
345
829
|
/**
|
|
346
830
|
*
|
|
347
831
|
* @param input - FILE_HEADER from step header
|
|
@@ -412,8 +896,7 @@ export class IfcApiProxyIfc {
|
|
|
412
896
|
return clone;
|
|
413
897
|
}
|
|
414
898
|
else {
|
|
415
|
-
Logger.error(`[GetGeometry]: Geometry Object not found for expressID:
|
|
416
|
-
${geometryExpressID}`);
|
|
899
|
+
Logger.error(`[GetGeometry]: Geometry Object not found for expressID: \n ${geometryExpressID}`);
|
|
417
900
|
}
|
|
418
901
|
}
|
|
419
902
|
}
|
|
@@ -506,6 +989,14 @@ export class IfcApiProxyIfc {
|
|
|
506
989
|
get sourceIsExternal() {
|
|
507
990
|
return this.model[0].isSourceExternal;
|
|
508
991
|
}
|
|
992
|
+
/**
|
|
993
|
+
* Store-backed pump split (prefetch / extract / release).
|
|
994
|
+
*
|
|
995
|
+
* @return {object} Cumulative milliseconds and pin telemetry.
|
|
996
|
+
*/
|
|
997
|
+
get extractProfile() {
|
|
998
|
+
return this.extractProfile_;
|
|
999
|
+
}
|
|
509
1000
|
/**
|
|
510
1001
|
* Release the resident source buffer and serve subsequent record
|
|
511
1002
|
* reads through fixed-size windows paged in from the given external
|
|
@@ -767,6 +1258,16 @@ export class IfcApiProxyIfc {
|
|
|
767
1258
|
/* eslint-enable no-unused-vars */
|
|
768
1259
|
return Array.from(coordinationMatrix);
|
|
769
1260
|
}
|
|
1261
|
+
/**
|
|
1262
|
+
* The coordination frame actually applied to emitted placements —
|
|
1263
|
+
* the derived (or validated adopted) recenter, identity when no
|
|
1264
|
+
* recenter ran. See ifc_api_model_passthrough.getAppliedCoordination.
|
|
1265
|
+
*
|
|
1266
|
+
* @return {Array<number>} column-major mat4
|
|
1267
|
+
*/
|
|
1268
|
+
getAppliedCoordination() {
|
|
1269
|
+
return [...(this.demandCoordination_ ?? this.identity)];
|
|
1270
|
+
}
|
|
770
1271
|
/**
|
|
771
1272
|
*
|
|
772
1273
|
* @param ptr
|
|
@@ -793,8 +1294,15 @@ export class IfcApiProxyIfc {
|
|
|
793
1294
|
* @return {Float32Array | Uint32Array}
|
|
794
1295
|
*/
|
|
795
1296
|
getSubArray(heap, startPtr, sizeBytes) {
|
|
796
|
-
//
|
|
797
|
-
|
|
1297
|
+
// `heap` stays in the signature because web-ifc's API puts it there, but
|
|
1298
|
+
// it is now read only for its element type. The view itself is rebuilt
|
|
1299
|
+
// over the module's CURRENT heap buffer: a caller-held HEAPF32/HEAPU32 can
|
|
1300
|
+
// be bound to a pre-growth buffer on the MT build, and subarray() on such
|
|
1301
|
+
// a view clamps the window silently and returns short data rather than
|
|
1302
|
+
// failing (#485, and see core/wasm_heap.ts).
|
|
1303
|
+
const arrayType = heap.constructor;
|
|
1304
|
+
// slice(0) as before, so the result outlives the next call into wasm.
|
|
1305
|
+
return wasmHeapView(this.wasmModule, arrayType, startPtr, sizeBytes).slice(0);
|
|
798
1306
|
}
|
|
799
1307
|
/**
|
|
800
1308
|
* Closes a model and frees all related memory
|
|
@@ -804,12 +1312,467 @@ export class IfcApiProxyIfc {
|
|
|
804
1312
|
closeModel() {
|
|
805
1313
|
// Null operation.
|
|
806
1314
|
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Free this model's native geometry (conway extension): every
|
|
1317
|
+
* canonical mesh the extraction produced plus the GetGeometry map.
|
|
1318
|
+
* Call AFTER the consumer has built its own scene from the meshes —
|
|
1319
|
+
* subsequent GetGeometry calls return an empty dummy. On a deferred
|
|
1320
|
+
* model whose pump has not drained, this is a no-op (releasing would
|
|
1321
|
+
* break the remaining extraction).
|
|
1322
|
+
*
|
|
1323
|
+
* The wasm heap never shrinks, but freed pages are reused: repeated
|
|
1324
|
+
* loads in one tab plateau instead of stacking whole model scenes
|
|
1325
|
+
* (the multi-load crash).
|
|
1326
|
+
*
|
|
1327
|
+
* @return {boolean} True when geometry was released.
|
|
1328
|
+
*/
|
|
1329
|
+
releaseGeometry() {
|
|
1330
|
+
if (this.deferredMode_ &&
|
|
1331
|
+
this.demandProducts_ !== void 0 &&
|
|
1332
|
+
(this.demandCursor_ < this.demandProducts_.length ||
|
|
1333
|
+
this.demandAggregatesCursor_ <
|
|
1334
|
+
(this.demandAggregates_?.length ?? 0))) {
|
|
1335
|
+
Logger.warning("[ReleaseModelGeometry]: deferred pump not drained \u2014 not releasing");
|
|
1336
|
+
return false;
|
|
1337
|
+
}
|
|
1338
|
+
const model = this.model[0];
|
|
1339
|
+
const localIDs = [];
|
|
1340
|
+
for (const mesh of model.geometry) {
|
|
1341
|
+
localIDs.push(mesh.localID);
|
|
1342
|
+
}
|
|
1343
|
+
for (const localID of localIDs) {
|
|
1344
|
+
try {
|
|
1345
|
+
model.geometry.delete(localID);
|
|
1346
|
+
}
|
|
1347
|
+
catch {
|
|
1348
|
+
// Never let a free break a loaded model.
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
// The GetGeometry map holds references to the now-freed natives —
|
|
1352
|
+
// clear it so lookups degrade to the dummy instead of touching them.
|
|
1353
|
+
this.model[3].clear();
|
|
1354
|
+
this.released_ = true;
|
|
1355
|
+
return true;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Deferred-mode batch pump (conway extension; Share demand/tiled
|
|
1359
|
+
* rendering slice A): extract the next `batchSize` products (file
|
|
1360
|
+
* order) through the per-product demand seam and emit THIS BATCH's
|
|
1361
|
+
* meshes through `meshCallback` — the incremental twin of
|
|
1362
|
+
* streamAllMeshes. Placed-geometry math (coordination, scaling,
|
|
1363
|
+
* centering) is identical; the shared meshMap is updated so
|
|
1364
|
+
* getFlatMesh keeps working. Call repeatedly until `remaining` is 0.
|
|
1365
|
+
*
|
|
1366
|
+
* Requires a model opened with deferred geometry
|
|
1367
|
+
* (`OpenModelStreamed(data, {..., DEFER_GEOMETRY: true})`); on a
|
|
1368
|
+
* fully-extracted model this is a no-op returning remaining 0.
|
|
1369
|
+
*
|
|
1370
|
+
* @param batchSize Max products to extract this call (min 1).
|
|
1371
|
+
* @param meshCallback Receives each newly-extracted product's mesh.
|
|
1372
|
+
* @return {object} `{extracted, remaining}` — products processed this
|
|
1373
|
+
* call and products still pending.
|
|
1374
|
+
*/
|
|
1375
|
+
extractGeometryBatch(batchSize, meshCallback) {
|
|
1376
|
+
// Fully-extracted opens have nothing to pump — re-running the
|
|
1377
|
+
// per-product extraction on them would duplicate scene work.
|
|
1378
|
+
if (!this.deferredMode_) {
|
|
1379
|
+
return { extracted: 0, remaining: 0 };
|
|
1380
|
+
}
|
|
1381
|
+
if (this.model[0].isSourceExternal) {
|
|
1382
|
+
throw new Error("ExtractGeometryBatch is synchronous and cannot page a windowed " +
|
|
1383
|
+
"source \u2014 use ExtractGeometryBatchAsync");
|
|
1384
|
+
}
|
|
1385
|
+
this.ensureDemandWorklists_();
|
|
1386
|
+
return this.pumpGeometryBatch_(batchSize, meshCallback);
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Async twin of {@link extractGeometryBatch}: pages each product's
|
|
1390
|
+
* `#ref` closure before extracting it, so a model opened through
|
|
1391
|
+
* {@link IfcApiProxyIfc.createFromStore} (windowed from birth) can
|
|
1392
|
+
* be pumped. Safe on a resident source (prefetch is a no-op).
|
|
1393
|
+
*
|
|
1394
|
+
* @param batchSize Max products to extract this call (min 1).
|
|
1395
|
+
* @param meshCallback Receives each newly-extracted product's mesh.
|
|
1396
|
+
* @return {Promise<object>} `{extracted, remaining}`.
|
|
1397
|
+
*/
|
|
1398
|
+
async extractGeometryBatchAsync(batchSize, meshCallback) {
|
|
1399
|
+
if (!this.deferredMode_) {
|
|
1400
|
+
return { extracted: 0, remaining: 0 };
|
|
1401
|
+
}
|
|
1402
|
+
this.ensureDemandWorklists_();
|
|
1403
|
+
if (!this.model[0].isSourceExternal) {
|
|
1404
|
+
return this.pumpGeometryBatch_(batchSize, meshCallback);
|
|
1405
|
+
}
|
|
1406
|
+
const products = this.demandProducts_ ?? [];
|
|
1407
|
+
const aggregates = this.demandAggregates_ ?? [];
|
|
1408
|
+
const totalWork = products.length + aggregates.length;
|
|
1409
|
+
const budget = Math.max(batchSize, 1);
|
|
1410
|
+
let extracted = 0;
|
|
1411
|
+
if (this.progressTracker_ !== void 0 && !this.geometryPhaseStarted_) {
|
|
1412
|
+
this.progressTracker_.beginPhase("geometry", "products", totalWork);
|
|
1413
|
+
this.geometryPhaseStarted_ = true;
|
|
1414
|
+
}
|
|
1415
|
+
const productEnd = Math.min(this.demandCursor_ + budget, products.length);
|
|
1416
|
+
const batchIDs = products.slice(this.demandCursor_, productEnd);
|
|
1417
|
+
if (batchIDs.length > 0) {
|
|
1418
|
+
// One pin set for the batch so mapped geometry stays resident
|
|
1419
|
+
// across the instances that share it.
|
|
1420
|
+
const pins = new Set();
|
|
1421
|
+
const leafSpans = [];
|
|
1422
|
+
const profile = this.extractProfile_;
|
|
1423
|
+
try {
|
|
1424
|
+
const prefetchStart = Date.now();
|
|
1425
|
+
await Promise.all(batchIDs.map((localID) => this.conwayGeometry_.ensureResidentForProductExtract(localID, pins, leafSpans)));
|
|
1426
|
+
profile.prefetchMs += Date.now() - prefetchStart;
|
|
1427
|
+
if (pins.size > profile.pinMax) {
|
|
1428
|
+
profile.pinMax = pins.size;
|
|
1429
|
+
}
|
|
1430
|
+
profile.lastPins = pins.size;
|
|
1431
|
+
const extractStart = Date.now();
|
|
1432
|
+
for (const localID of batchIDs) {
|
|
1433
|
+
try {
|
|
1434
|
+
if (this.conwayGeometry_.extractProductGeometryByLocalID(localID)) {
|
|
1435
|
+
++extracted;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
catch (error) {
|
|
1439
|
+
Logger.error(`Error extracting product localID ${localID}: ` +
|
|
1440
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
1441
|
+
}
|
|
1442
|
+
// Drop JS views after each product; chunks stay pinned for
|
|
1443
|
+
// the rest of the batch so rematerialise is a cache hit.
|
|
1444
|
+
this.model[0].releaseSourceViews(pins);
|
|
1445
|
+
}
|
|
1446
|
+
profile.extractMs += Date.now() - extractStart;
|
|
1447
|
+
this.demandCursor_ = productEnd;
|
|
1448
|
+
}
|
|
1449
|
+
finally {
|
|
1450
|
+
const releaseStart = Date.now();
|
|
1451
|
+
this.model[0].releaseSourceViews(pins);
|
|
1452
|
+
this.model[0].unpinLocalIDs(pins);
|
|
1453
|
+
for (const span of leafSpans) {
|
|
1454
|
+
this.model[0].unpinAddressRange(span.address, span.length);
|
|
1455
|
+
}
|
|
1456
|
+
profile.releaseMs += Date.now() - releaseStart;
|
|
1457
|
+
profile.batches++;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
if (this.demandCursor_ >= products.length &&
|
|
1461
|
+
this.demandAggregatesCursor_ < aggregates.length) {
|
|
1462
|
+
const aggregatesEnd = Math.min(this.demandAggregatesCursor_ + (budget - extracted), aggregates.length);
|
|
1463
|
+
for (; this.demandAggregatesCursor_ < aggregatesEnd; ++this.demandAggregatesCursor_) {
|
|
1464
|
+
const relAggregate = aggregates[this.demandAggregatesCursor_];
|
|
1465
|
+
const leafSpans = [];
|
|
1466
|
+
const pins = await this.conwayGeometry_.ensureResidentForAggregateExtract(relAggregate, leafSpans);
|
|
1467
|
+
try {
|
|
1468
|
+
this.conwayGeometry_.extractRelAggregateGeometry(relAggregate);
|
|
1469
|
+
++extracted;
|
|
1470
|
+
}
|
|
1471
|
+
catch (error) {
|
|
1472
|
+
Logger.error(`Error extracting aggregate ${relAggregate.expressID}: ` +
|
|
1473
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
1474
|
+
}
|
|
1475
|
+
finally {
|
|
1476
|
+
this.model[0].releaseSourceViews(pins);
|
|
1477
|
+
this.model[0].unpinLocalIDs(pins);
|
|
1478
|
+
for (const span of leafSpans) {
|
|
1479
|
+
this.model[0].unpinAddressRange(span.address, span.length);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
if (meshCallback !== void 0) {
|
|
1485
|
+
this.streamNewMeshes_(meshCallback);
|
|
1486
|
+
}
|
|
1487
|
+
const remaining = (products.length - this.demandCursor_) +
|
|
1488
|
+
(aggregates.length - this.demandAggregatesCursor_);
|
|
1489
|
+
const windowMb = this.model[0].residentSourceBytes / BYTES_PER_MIB;
|
|
1490
|
+
if (this.progressTracker_ !== void 0) {
|
|
1491
|
+
const completed = totalWork - remaining;
|
|
1492
|
+
if (remaining === 0) {
|
|
1493
|
+
this.progressTracker_.update(completed, { residentSourceMb: windowMb });
|
|
1494
|
+
this.progressTracker_.endPhase(totalWork);
|
|
1495
|
+
}
|
|
1496
|
+
else {
|
|
1497
|
+
this.progressTracker_.update(completed, { residentSourceMb: windowMb });
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
return { extracted, remaining };
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Enumerate the deferred worklists once (file-order products, then
|
|
1504
|
+
* rel-aggregates). Shared by the sync and async pumps.
|
|
1505
|
+
*/
|
|
1506
|
+
ensureDemandWorklists_() {
|
|
1507
|
+
if (this.demandProducts_ !== void 0) {
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
// Aggregate-target products are extracted ONLY by the
|
|
1511
|
+
// rel-aggregates pass below (with the relating object's master
|
|
1512
|
+
// rel-voids), never by the per-product pass: extracting them here
|
|
1513
|
+
// first would emit their instances with the uncut/placeholder
|
|
1514
|
+
// content and the pass's later replacement would never reach an
|
|
1515
|
+
// incremental consumer (it copies at delivery), while the pass's
|
|
1516
|
+
// second scene instance would draw over the first (see
|
|
1517
|
+
// aggregateTargetLocalIDs).
|
|
1518
|
+
const aggregateTargets = this.conwayGeometry_.aggregateTargetLocalIDs();
|
|
1519
|
+
const products = [];
|
|
1520
|
+
for (const product of this.model[0].types(IfcProduct)) {
|
|
1521
|
+
if (aggregateTargets.has(product.localID)) {
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
products.push(product.localID);
|
|
1525
|
+
}
|
|
1526
|
+
const aggregates = [];
|
|
1527
|
+
for (const relAggregate of this.model[0].types(IfcRelAggregates)) {
|
|
1528
|
+
aggregates.push(relAggregate);
|
|
1529
|
+
}
|
|
1530
|
+
this.demandProducts_ = products;
|
|
1531
|
+
this.demandAggregates_ = aggregates;
|
|
1532
|
+
this.demandCursor_ = 0;
|
|
1533
|
+
this.demandAggregatesCursor_ = 0;
|
|
1534
|
+
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Synchronous extract of the next batch. Caller must have paged
|
|
1537
|
+
* ranges if the source is windowed.
|
|
1538
|
+
*
|
|
1539
|
+
* @param batchSize Max products this call.
|
|
1540
|
+
* @param meshCallback Optional mesh consumer.
|
|
1541
|
+
* @return {object} `{extracted, remaining}`.
|
|
1542
|
+
*/
|
|
1543
|
+
pumpGeometryBatch_(batchSize, meshCallback) {
|
|
1544
|
+
const products = this.demandProducts_ ?? [];
|
|
1545
|
+
const aggregates = this.demandAggregates_ ?? [];
|
|
1546
|
+
const totalWork = products.length + aggregates.length;
|
|
1547
|
+
if (this.progressTracker_ !== void 0 && !this.geometryPhaseStarted_) {
|
|
1548
|
+
this.progressTracker_.beginPhase("geometry", "products", totalWork);
|
|
1549
|
+
this.geometryPhaseStarted_ = true;
|
|
1550
|
+
}
|
|
1551
|
+
const budget = Math.max(batchSize, 1);
|
|
1552
|
+
const end = Math.min(this.demandCursor_ + budget, products.length);
|
|
1553
|
+
let extracted = 0;
|
|
1554
|
+
for (; this.demandCursor_ < end; ++this.demandCursor_) {
|
|
1555
|
+
const localID = products[this.demandCursor_];
|
|
1556
|
+
if (this.conwayGeometry_.extractProductGeometryByLocalID(localID)) {
|
|
1557
|
+
++extracted;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
// Classic parity: once the product walk completes, pump the
|
|
1561
|
+
// whole-model walk's second (rel-aggregates master-voids) pass with
|
|
1562
|
+
// the same per-call budget — batch-by-batch, not as one end-of-load
|
|
1563
|
+
// stall — so aggregate parts stream in cut, exactly once, with
|
|
1564
|
+
// final content (see demandAggregates_).
|
|
1565
|
+
if (this.demandCursor_ >= products.length &&
|
|
1566
|
+
this.demandAggregatesCursor_ < aggregates.length) {
|
|
1567
|
+
const aggregatesEnd = Math.min(this.demandAggregatesCursor_ + (budget - extracted), aggregates.length);
|
|
1568
|
+
for (; this.demandAggregatesCursor_ < aggregatesEnd; ++this.demandAggregatesCursor_) {
|
|
1569
|
+
this.conwayGeometry_.extractRelAggregateGeometry(aggregates[this.demandAggregatesCursor_]);
|
|
1570
|
+
++extracted;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
if (meshCallback !== void 0) {
|
|
1574
|
+
this.streamNewMeshes_(meshCallback);
|
|
1575
|
+
}
|
|
1576
|
+
const remaining = (products.length - this.demandCursor_) +
|
|
1577
|
+
(aggregates.length - this.demandAggregatesCursor_);
|
|
1578
|
+
if (this.progressTracker_ !== void 0) {
|
|
1579
|
+
const completed = totalWork - remaining;
|
|
1580
|
+
if (remaining === 0) {
|
|
1581
|
+
this.progressTracker_.endPhase(totalWork);
|
|
1582
|
+
}
|
|
1583
|
+
else {
|
|
1584
|
+
this.progressTracker_.update(completed);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
return {
|
|
1588
|
+
extracted,
|
|
1589
|
+
remaining,
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* Walk the scene and emit every not-yet-captured placed instance as
|
|
1594
|
+
* per-entity DELTA FlatMeshes — the incremental core of
|
|
1595
|
+
* streamAllMeshes with identical placed-geometry math, processed in
|
|
1596
|
+
* walk order exactly once per instance (per-entity watermarks). An
|
|
1597
|
+
* entity re-emits with only its NEW instances when shared/mapped
|
|
1598
|
+
* geometry attributes more to it in later batches; consumers render
|
|
1599
|
+
* deltas additively (the shared meshMap still accumulates each
|
|
1600
|
+
* entity's FULL vector, so getFlatMesh stays whole-model correct).
|
|
1601
|
+
*
|
|
1602
|
+
* Also fixes a latent multi-call bug: the derived coordination
|
|
1603
|
+
* matrix is remembered (demandCoordination_), so later batches place
|
|
1604
|
+
* with the SAME coordination the first batch established
|
|
1605
|
+
* (streamAllMeshes never needed this — it runs once). It is NOT
|
|
1606
|
+
* exposed through getCoordinationMatrix, which keeps the classic
|
|
1607
|
+
* identity contract consumers stamp onto assembled models.
|
|
1608
|
+
*
|
|
1609
|
+
* @param meshCallback Receives one delta FlatMesh per entity that
|
|
1610
|
+
* gained instances this call.
|
|
1611
|
+
*/
|
|
1612
|
+
streamNewMeshes_(meshCallback) {
|
|
1613
|
+
// Released models: the scene's natives are freed — nothing new can
|
|
1614
|
+
// exist to capture, and walking would touch freed objects.
|
|
1615
|
+
if (this.released_) {
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
const [model, scene, meshMap, geometryMaterialTransformMap] = this.model;
|
|
1619
|
+
let coordinationMatrix = this.demandCoordination_ ?? glmatrix.mat4.create();
|
|
1620
|
+
const seenThisPass = new Map();
|
|
1621
|
+
const deltas = new Map();
|
|
1622
|
+
// eslint-disable-next-line no-unused-vars
|
|
1623
|
+
for (const [_, nativeTransform, geometry, material, entity] of scene.walk()) {
|
|
1624
|
+
if (entity?.localID === void 0 || entity.expressID === void 0) {
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
// Per-entity walk position vs watermark: instances before the
|
|
1628
|
+
// watermark were captured in an earlier call (append-only walk
|
|
1629
|
+
// order makes the count a stable cursor).
|
|
1630
|
+
const walkIndex = seenThisPass.get(entity.localID) ?? 0;
|
|
1631
|
+
seenThisPass.set(entity.localID, walkIndex + 1);
|
|
1632
|
+
if (walkIndex < (this.demandCapturedCounts_.get(entity.localID) ?? 0)) {
|
|
1633
|
+
continue;
|
|
1634
|
+
}
|
|
1635
|
+
if (geometry.type !== CanonicalMeshType.BUFFER_GEOMETRY || geometry.temporary) {
|
|
1636
|
+
continue;
|
|
1637
|
+
}
|
|
1638
|
+
const material_ = material ?? {
|
|
1639
|
+
name: "",
|
|
1640
|
+
// eslint-disable-next-line no-magic-numbers
|
|
1641
|
+
baseColor: [0.8, 0.8, 0.8, 1],
|
|
1642
|
+
// eslint-disable-next-line no-magic-numbers
|
|
1643
|
+
legacyColor: [0.8, 0.8, 0.8, 1],
|
|
1644
|
+
doubleSided: true,
|
|
1645
|
+
blend: 0,
|
|
1646
|
+
};
|
|
1647
|
+
const validatePreviewFrame = this.demandCoordinationFromPreview_ &&
|
|
1648
|
+
this.settings?.COORDINATE_TO_ORIGIN === true;
|
|
1649
|
+
let nativePt;
|
|
1650
|
+
if ((!this._isCoordinated || validatePreviewFrame) &&
|
|
1651
|
+
this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1652
|
+
nativePt = geometry.geometry.getPoint(0);
|
|
1653
|
+
}
|
|
1654
|
+
// normalize() recenters the shared geometry buffer (side effect)
|
|
1655
|
+
// and returns the local centre used to place it.
|
|
1656
|
+
const center = geometry.geometry.normalize();
|
|
1657
|
+
const expressID = model.getElementByLocalID(geometry.localID)?.expressID;
|
|
1658
|
+
// Full-precision float64 placement straight from the wasm boundary
|
|
1659
|
+
// (glm::dmat4). NOT re-truncated through a gl-matrix Float32Array —
|
|
1660
|
+
// the recentre math runs in double precision (see coordination_f64).
|
|
1661
|
+
const geometryTransform = nativeTransform?.getValues();
|
|
1662
|
+
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1663
|
+
const derived = deriveCoordinationF64(geometryTransform, nativePt, this.NormalizeMat, this.linearScalingFactor);
|
|
1664
|
+
coordinationMatrix = derived;
|
|
1665
|
+
// Persist for every later batch (internal only — see
|
|
1666
|
+
// demandCoordination_'s identity-contract note).
|
|
1667
|
+
this.demandCoordination_ = derived;
|
|
1668
|
+
this._isCoordinated = true;
|
|
1669
|
+
}
|
|
1670
|
+
else if (validatePreviewFrame) {
|
|
1671
|
+
// One-shot check of an adopted preview frame against the durable
|
|
1672
|
+
// walk's first geometry: when the composed placement still lands
|
|
1673
|
+
// beyond the large-coordinate budget, the preview anchored in a
|
|
1674
|
+
// different frame than the model body (Share#1634) — re-derive
|
|
1675
|
+
// from this geometry, the classic path's anchor. The throwaway
|
|
1676
|
+
// preview scene may briefly disagree; the durable model must
|
|
1677
|
+
// place like the classic open.
|
|
1678
|
+
this.demandCoordinationFromPreview_ = false;
|
|
1679
|
+
const probe = composeTransformF64(coordinationMatrix, geometryTransform, center);
|
|
1680
|
+
const magnitude = Math.max(Math.abs(probe[TRANSLATION_X]), Math.abs(probe[TRANSLATION_Y]), Math.abs(probe[TRANSLATION_Z]));
|
|
1681
|
+
if (magnitude > LARGE_COORDINATE_BUDGET_M) {
|
|
1682
|
+
const derived = deriveCoordinationF64(geometryTransform, nativePt, this.NormalizeMat, this.linearScalingFactor);
|
|
1683
|
+
coordinationMatrix = derived;
|
|
1684
|
+
this.demandCoordination_ = derived;
|
|
1685
|
+
Logger.info(`[deferred] preview coordination frame rejected (first durable ` +
|
|
1686
|
+
`placement at ${Math.round(magnitude)}m); re-derived from the durable anchor`);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
const newTransformArr = composeTransformF64(coordinationMatrix, geometryTransform, center);
|
|
1690
|
+
geometryMaterialTransformMap.set(expressID, [geometry.geometry, material_, newTransformArr]);
|
|
1691
|
+
const color = {
|
|
1692
|
+
x: material_.legacyColor[0],
|
|
1693
|
+
y: material_.legacyColor[1],
|
|
1694
|
+
z: material_.legacyColor[2],
|
|
1695
|
+
w: material_.legacyColor[3],
|
|
1696
|
+
};
|
|
1697
|
+
const placed = {
|
|
1698
|
+
color,
|
|
1699
|
+
geometryExpressID: expressID,
|
|
1700
|
+
flatTransformation: newTransformArr,
|
|
1701
|
+
};
|
|
1702
|
+
let mesh = meshMap.get(entity.expressID);
|
|
1703
|
+
if (mesh === void 0) {
|
|
1704
|
+
const placedArray = new Array();
|
|
1705
|
+
const placedVector = {
|
|
1706
|
+
get: (index) => placedArray[index] ?? placed,
|
|
1707
|
+
size: () => placedArray.length,
|
|
1708
|
+
push: (parameter) => {
|
|
1709
|
+
placedArray.push(parameter);
|
|
1710
|
+
},
|
|
1711
|
+
};
|
|
1712
|
+
const flatMesh = {
|
|
1713
|
+
geometries: placedVector,
|
|
1714
|
+
expressID: entity.expressID,
|
|
1715
|
+
};
|
|
1716
|
+
mesh = [placedVector, flatMesh];
|
|
1717
|
+
meshMap.set(entity.expressID, mesh);
|
|
1718
|
+
}
|
|
1719
|
+
mesh[0].push(placed);
|
|
1720
|
+
mesh[1].geometries = mesh[0];
|
|
1721
|
+
this.demandCapturedCounts_.set(entity.localID, (this.demandCapturedCounts_.get(entity.localID) ?? 0) + 1);
|
|
1722
|
+
let delta = deltas.get(entity.expressID);
|
|
1723
|
+
if (delta === void 0) {
|
|
1724
|
+
delta = [];
|
|
1725
|
+
deltas.set(entity.expressID, delta);
|
|
1726
|
+
}
|
|
1727
|
+
delta.push(placed);
|
|
1728
|
+
}
|
|
1729
|
+
const vectorFlatMesh = this.model[4];
|
|
1730
|
+
for (const [expressID, placedList] of deltas) {
|
|
1731
|
+
const placedVector = {
|
|
1732
|
+
get: (index) => placedList[index] ?? placedList[0],
|
|
1733
|
+
size: () => placedList.length,
|
|
1734
|
+
push: (parameter) => {
|
|
1735
|
+
placedList.push(parameter);
|
|
1736
|
+
},
|
|
1737
|
+
};
|
|
1738
|
+
const deltaMesh = { geometries: placedVector, expressID };
|
|
1739
|
+
vectorFlatMesh.push(deltaMesh);
|
|
1740
|
+
meshCallback(deltaMesh);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
807
1743
|
/**
|
|
808
1744
|
*
|
|
809
1745
|
* @param modelID
|
|
810
1746
|
* @param meshCallback
|
|
811
1747
|
*/
|
|
812
1748
|
streamAllMeshes(meshCallback) {
|
|
1749
|
+
// Released models: the natives behind the scene are freed — serve
|
|
1750
|
+
// the accumulated per-entity meshes instead of re-walking.
|
|
1751
|
+
if (this.released_ && !this.deferredMode_) {
|
|
1752
|
+
const [, , meshMap, , vectorFlatMesh] = this.model;
|
|
1753
|
+
meshMap.forEach((mesh) => {
|
|
1754
|
+
vectorFlatMesh.push(mesh[1]);
|
|
1755
|
+
meshCallback(mesh[1]);
|
|
1756
|
+
});
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
// Deferred models: the delta capture has already populated (or will
|
|
1760
|
+
// populate) the shared meshMap — re-running the classic walk would
|
|
1761
|
+
// push every instance a second time. Pump any remainder to
|
|
1762
|
+
// completion and serve the accumulated full per-entity meshes.
|
|
1763
|
+
if (this.deferredMode_) {
|
|
1764
|
+
const noCallback = void 0;
|
|
1765
|
+
while (this.extractGeometryBatch(DEFERRED_DRAIN_BATCH, noCallback).remaining > 0) {
|
|
1766
|
+
// draining
|
|
1767
|
+
}
|
|
1768
|
+
this.streamNewMeshes_(() => { });
|
|
1769
|
+
const [, , meshMap, , vectorFlatMesh] = this.model;
|
|
1770
|
+
meshMap.forEach((mesh) => {
|
|
1771
|
+
vectorFlatMesh.push(mesh[1]);
|
|
1772
|
+
meshCallback(mesh[1]);
|
|
1773
|
+
});
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
813
1776
|
const [model, scene, meshMap, geometryMaterialTransformMap, vectorFlatMesh] = this.model;
|
|
814
1777
|
let coordinationMatrix = this.model[5];
|
|
815
1778
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -834,62 +1797,23 @@ export class IfcApiProxyIfc {
|
|
|
834
1797
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
835
1798
|
nativePt = geometry.geometry.getPoint(0);
|
|
836
1799
|
}
|
|
837
|
-
//
|
|
838
|
-
|
|
1800
|
+
// normalize() recenters the geometry buffer (side effect) and
|
|
1801
|
+
// returns the local centre used to place it.
|
|
839
1802
|
const center = geometry.geometry.normalize();
|
|
840
|
-
geomCenter[0] = center.x;
|
|
841
|
-
geomCenter[1] = center.y;
|
|
842
|
-
geomCenter[2] = center.z;
|
|
843
|
-
// Create a translation matrix from geom.min
|
|
844
|
-
const translationMatrixGeomMin = glmatrix.mat4.create();
|
|
845
|
-
glmatrix.mat4.fromTranslation(translationMatrixGeomMin, geomCenter);
|
|
846
1803
|
// create PlacedGeometry
|
|
847
1804
|
const expressID = model.getElementByLocalID(geometry.localID)?.expressID;
|
|
1805
|
+
// Full-precision float64 placement straight from the wasm boundary
|
|
1806
|
+
// (glm::dmat4) — never truncated through a gl-matrix Float32Array;
|
|
1807
|
+
// the recentre math runs in double precision (see coordination_f64).
|
|
848
1808
|
const geometryTransform = nativeTransform?.getValues();
|
|
849
|
-
let newMatrix;
|
|
850
|
-
if (geometryTransform !== void 0) {
|
|
851
|
-
newMatrix = glmatrix.mat4.fromValues(geometryTransform[0], geometryTransform[1], geometryTransform[2], geometryTransform[3], geometryTransform[4], geometryTransform[5], geometryTransform[6], geometryTransform[7], geometryTransform[8], geometryTransform[9], geometryTransform[10], geometryTransform[11], geometryTransform[12], geometryTransform[13], geometryTransform[14], geometryTransform[15]);
|
|
852
|
-
}
|
|
853
|
-
else {
|
|
854
|
-
// set to identity if no transform found
|
|
855
|
-
newMatrix = glmatrix.mat4.create();
|
|
856
|
-
}
|
|
857
1809
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
//
|
|
861
|
-
|
|
862
|
-
glmatrix.vec4.transformMat4(transformedPt, [pt[0], pt[1], pt[2], 1], newMatrix);
|
|
863
|
-
// Create the translation matrix.
|
|
864
|
-
coordinationMatrix = glmatrix.mat4.create();
|
|
865
|
-
glmatrix.mat4.fromTranslation(coordinationMatrix, [-transformedPt[0], -transformedPt[1], -transformedPt[2]]);
|
|
866
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
867
|
-
// Create a 3D vector for scaling factors
|
|
868
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
869
|
-
// Scale the matrix
|
|
870
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
871
|
-
glmatrix.mat4.multiply(coordinationMatrix, this.NormalizeMat, coordinationMatrix);
|
|
872
|
-
glmatrix.mat4.multiply(coordinationMatrix, scaleMatrix, coordinationMatrix);
|
|
1810
|
+
coordinationMatrix = deriveCoordinationF64(geometryTransform, nativePt, this.NormalizeMat, this.linearScalingFactor);
|
|
1811
|
+
// Persisted for getAppliedCoordination (Share#1634): report
|
|
1812
|
+
// the real applied frame, not the classic silent identity.
|
|
1813
|
+
this.demandCoordination_ = Array.from(coordinationMatrix);
|
|
873
1814
|
this._isCoordinated = true;
|
|
874
1815
|
}
|
|
875
|
-
|
|
876
|
-
const newTransform = glmatrix.mat4.create();
|
|
877
|
-
// Create a 4x4 identity matrix
|
|
878
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
879
|
-
// Create a 3D vector for scaling factors
|
|
880
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
881
|
-
// Scale the matrix
|
|
882
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
883
|
-
// Perform the matrix multiplications
|
|
884
|
-
if (newMatrix !== void 0) {
|
|
885
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newMatrix);
|
|
886
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
887
|
-
}
|
|
888
|
-
else {
|
|
889
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newTransform);
|
|
890
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
891
|
-
}
|
|
892
|
-
const newTransformArr = Array.from(newTransform);
|
|
1816
|
+
const newTransformArr = composeTransformF64(coordinationMatrix, geometryTransform, center);
|
|
893
1817
|
geometryMaterialTransformMap.set(expressID, [geometry.geometry, material_, newTransformArr]);
|
|
894
1818
|
if (entity?.localID !== void 0) {
|
|
895
1819
|
if (entity?.expressID !== void 0) {
|
|
@@ -1003,62 +1927,23 @@ export class IfcApiProxyIfc {
|
|
|
1003
1927
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1004
1928
|
nativePt = geometry.geometry.getPoint(0);
|
|
1005
1929
|
}
|
|
1006
|
-
//
|
|
1007
|
-
|
|
1930
|
+
// normalize() recenters the geometry buffer (side effect) and
|
|
1931
|
+
// returns the local centre used to place it.
|
|
1008
1932
|
const center = geometry.geometry.normalize();
|
|
1009
|
-
geomCenter[0] = center.x;
|
|
1010
|
-
geomCenter[1] = center.y;
|
|
1011
|
-
geomCenter[2] = center.z;
|
|
1012
|
-
// Create a translation matrix from geom.min
|
|
1013
|
-
const translationMatrixGeomMin = glmatrix.mat4.create();
|
|
1014
|
-
glmatrix.mat4.fromTranslation(translationMatrixGeomMin, geomCenter);
|
|
1015
1933
|
// create PlacedGeometry
|
|
1016
1934
|
const expressID = model.getElementByLocalID(geometry.localID)?.expressID;
|
|
1935
|
+
// Full-precision float64 placement straight from the wasm boundary
|
|
1936
|
+
// (glm::dmat4) — never truncated through a gl-matrix Float32Array;
|
|
1937
|
+
// the recentre math runs in double precision (see coordination_f64).
|
|
1017
1938
|
const geometryTransform = nativeTransform?.getValues();
|
|
1018
|
-
let newMatrix;
|
|
1019
|
-
if (geometryTransform !== void 0) {
|
|
1020
|
-
newMatrix = glmatrix.mat4.fromValues(geometryTransform[0], geometryTransform[1], geometryTransform[2], geometryTransform[3], geometryTransform[4], geometryTransform[5], geometryTransform[6], geometryTransform[7], geometryTransform[8], geometryTransform[9], geometryTransform[10], geometryTransform[11], geometryTransform[12], geometryTransform[13], geometryTransform[14], geometryTransform[15]);
|
|
1021
|
-
}
|
|
1022
1939
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1023
|
-
// coordinate the geometry to the origin
|
|
1024
|
-
// Assuming geom.GetPoint(0) returns a glm::dvec3, i.e., a 3D vector.
|
|
1025
|
-
// In TypeScript, you can represent it as number[] or Float64Array.
|
|
1026
1940
|
Logger.info("Setting up coordinationMatrix");
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
const transformedPt = glmatrix.vec4.create();
|
|
1031
|
-
glmatrix.vec4.transformMat4(transformedPt, [pt[0], pt[1], pt[2], 1], newMatrix);
|
|
1032
|
-
// Create the translation matrix.
|
|
1033
|
-
coordinationMatrix = glmatrix.mat4.create();
|
|
1034
|
-
glmatrix.mat4.fromTranslation(coordinationMatrix, [-transformedPt[0], -transformedPt[1], -transformedPt[2]]);
|
|
1035
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
1036
|
-
// Create a 3D vector for scaling factors
|
|
1037
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
1038
|
-
// Scale the matrix
|
|
1039
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
1040
|
-
glmatrix.mat4.multiply(coordinationMatrix, this.NormalizeMat, coordinationMatrix);
|
|
1041
|
-
glmatrix.mat4.multiply(coordinationMatrix, scaleMatrix, coordinationMatrix);
|
|
1941
|
+
coordinationMatrix = deriveCoordinationF64(geometryTransform, nativePt, this.NormalizeMat, this.linearScalingFactor);
|
|
1942
|
+
// Persisted for getAppliedCoordination (Share#1634).
|
|
1943
|
+
this.demandCoordination_ = Array.from(coordinationMatrix);
|
|
1042
1944
|
this._isCoordinated = true;
|
|
1043
1945
|
}
|
|
1044
|
-
|
|
1045
|
-
const newTransform = glmatrix.mat4.create();
|
|
1046
|
-
// Create a 4x4 identity matrix
|
|
1047
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
1048
|
-
// Create a 3D vector for scaling factors
|
|
1049
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
1050
|
-
// Scale the matrix
|
|
1051
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
1052
|
-
// Perform the matrix multiplications
|
|
1053
|
-
if (newMatrix !== void 0) {
|
|
1054
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newMatrix);
|
|
1055
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
1056
|
-
}
|
|
1057
|
-
else {
|
|
1058
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newTransform);
|
|
1059
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
1060
|
-
}
|
|
1061
|
-
const newTransformArr = Array.from(newTransform);
|
|
1946
|
+
const newTransformArr = composeTransformF64(coordinationMatrix, geometryTransform, center);
|
|
1062
1947
|
geometryMaterialTransformMap.set(expressID, [geometry.geometry, material_, newTransformArr]);
|
|
1063
1948
|
if (entity?.localID !== void 0) {
|
|
1064
1949
|
if (entity?.expressID !== void 0) {
|
|
@@ -1158,61 +2043,23 @@ export class IfcApiProxyIfc {
|
|
|
1158
2043
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1159
2044
|
nativePt = geometry.geometry.getPoint(0);
|
|
1160
2045
|
}
|
|
1161
|
-
//
|
|
1162
|
-
|
|
2046
|
+
// normalize() recenters the geometry buffer (side effect) and
|
|
2047
|
+
// returns the local centre used to place it.
|
|
1163
2048
|
const center = geometry.geometry.normalize();
|
|
1164
|
-
geomCenter[0] = center.x;
|
|
1165
|
-
geomCenter[1] = center.y;
|
|
1166
|
-
geomCenter[2] = center.z;
|
|
1167
|
-
// Create a translation matrix from geom.min
|
|
1168
|
-
const translationMatrixGeomMin = glmatrix.mat4.create();
|
|
1169
|
-
glmatrix.mat4.fromTranslation(translationMatrixGeomMin, geomCenter);
|
|
1170
2049
|
// create PlacedGeometry
|
|
1171
2050
|
const expressID = model.getElementByLocalID(geometry.localID)?.expressID;
|
|
2051
|
+
// Full-precision float64 placement straight from the wasm boundary
|
|
2052
|
+
// (glm::dmat4) — never truncated through a gl-matrix Float32Array;
|
|
2053
|
+
// the recentre math runs in double precision (see coordination_f64).
|
|
1172
2054
|
const geometryTransform = nativeTransform?.getValues();
|
|
1173
|
-
let newMatrix;
|
|
1174
|
-
if (geometryTransform !== void 0) {
|
|
1175
|
-
newMatrix = glmatrix.mat4.fromValues(geometryTransform[0], geometryTransform[1], geometryTransform[2], geometryTransform[3], geometryTransform[4], geometryTransform[5], geometryTransform[6], geometryTransform[7], geometryTransform[8], geometryTransform[9], geometryTransform[10], geometryTransform[11], geometryTransform[12], geometryTransform[13], geometryTransform[14], geometryTransform[15]);
|
|
1176
|
-
}
|
|
1177
2055
|
if (!this._isCoordinated && this.settings?.COORDINATE_TO_ORIGIN) {
|
|
1178
|
-
// coordinate the geometry to the origin
|
|
1179
|
-
// Assuming geom.GetPoint(0) returns a glm::dvec3, i.e., a 3D vector.
|
|
1180
|
-
// In TypeScript, you can represent it as number[] or Float64Array.
|
|
1181
2056
|
Logger.info("Setting up coordinationMatrix");
|
|
1182
|
-
|
|
1183
|
-
//
|
|
1184
|
-
|
|
1185
|
-
glmatrix.vec4.transformMat4(transformedPt, [pt[0], pt[1], pt[2], 1], newMatrix);
|
|
1186
|
-
// Create the translation matrix.
|
|
1187
|
-
coordinationMatrix = glmatrix.mat4.create();
|
|
1188
|
-
glmatrix.mat4.fromTranslation(coordinationMatrix, [-transformedPt[0], -transformedPt[1], -transformedPt[2]]);
|
|
1189
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
1190
|
-
// Create a 3D vector for scaling factors
|
|
1191
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
1192
|
-
// Scale the matrix
|
|
1193
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
1194
|
-
glmatrix.mat4.multiply(coordinationMatrix, this.NormalizeMat, coordinationMatrix);
|
|
1195
|
-
glmatrix.mat4.multiply(coordinationMatrix, scaleMatrix, coordinationMatrix);
|
|
2057
|
+
coordinationMatrix = deriveCoordinationF64(geometryTransform, nativePt, this.NormalizeMat, this.linearScalingFactor);
|
|
2058
|
+
// Persisted for getAppliedCoordination (Share#1634).
|
|
2059
|
+
this.demandCoordination_ = Array.from(coordinationMatrix);
|
|
1196
2060
|
this._isCoordinated = true;
|
|
1197
2061
|
}
|
|
1198
|
-
|
|
1199
|
-
const newTransform = glmatrix.mat4.create();
|
|
1200
|
-
// Create a 4x4 identity matrix
|
|
1201
|
-
const scaleMatrix = glmatrix.mat4.create();
|
|
1202
|
-
// Create a 3D vector for scaling factors
|
|
1203
|
-
const scaleVec = glmatrix.vec3.fromValues(this.linearScalingFactor, this.linearScalingFactor, this.linearScalingFactor);
|
|
1204
|
-
// Scale the matrix
|
|
1205
|
-
glmatrix.mat4.scale(scaleMatrix, scaleMatrix, scaleVec);
|
|
1206
|
-
// Perform the matrix multiplications
|
|
1207
|
-
if (newMatrix !== void 0) {
|
|
1208
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newMatrix);
|
|
1209
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
1210
|
-
}
|
|
1211
|
-
else {
|
|
1212
|
-
glmatrix.mat4.multiply(newTransform, coordinationMatrix, newTransform);
|
|
1213
|
-
glmatrix.mat4.multiply(newTransform, newTransform, translationMatrixGeomMin);
|
|
1214
|
-
}
|
|
1215
|
-
const newTransformArr = Array.from(newTransform);
|
|
2062
|
+
const newTransformArr = composeTransformF64(coordinationMatrix, geometryTransform, center);
|
|
1216
2063
|
geometryMaterialTransformMap.set(expressID, [geometry.geometry, material_, newTransformArr]);
|
|
1217
2064
|
if (entity?.localID !== void 0) {
|
|
1218
2065
|
if (entity?.expressID !== void 0) {
|