resqpy 5.0.0__tar.gz → 5.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {resqpy-5.0.0 → resqpy-5.1.0}/PKG-INFO +2 -2
- {resqpy-5.0.0 → resqpy-5.1.0}/pyproject.toml +1 -1
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/__init__.py +1 -1
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/_find_faces.py +95 -29
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_model.py +5 -7
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/wrappers/grid_surface_mp.py +90 -43
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/triangulation.py +16 -15
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/_collection_get_attributes.py +2 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_surface.py +167 -19
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_tri_mesh.py +3 -1
- {resqpy-5.0.0 → resqpy-5.1.0}/LICENSE +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/README.md +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/crs.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_edges_per_column_property_array.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_faults.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_one_blocked_well_property.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_one_grid_property_array.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_single_cell_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_wells_from_ascii_file.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_add_zone_by_layer_property.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_coarsened_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_common.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_copy_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_drape_to_surface.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_extract_box.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_extract_box_for_well.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_fault_throw_scaling.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_gather_ensemble.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_interpolated_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_local_depth_adjustment.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_refined_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_tilted_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_unsplit_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_zonal_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/derived_model/_zone_layer_ranges_from_array.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/fault/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/fault/_gcs_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/fault/_grid_connection_set.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_cell_properties.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_connection_sets.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_create_grid_xml.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_defined_geometry.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_extract_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_face_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_faults.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_grid_types.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_intervals_info.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_pillars.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_pixel_maps.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_points_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_regular_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_transmissibility.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_write_hdf5_from_caches.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_write_nexus_corp.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid/_xyz.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/_blocked_well_populate.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/_grid_skin.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/_grid_surface.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/_trajectory_intersects.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/grid_surface/grid_surface_cuda.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/lines/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/lines/_common.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/lines/_polyline.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/lines/_polyline_set.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_catalogue.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_context.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_forestry.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_grids.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_hdf5.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/model/_xml.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/_multiprocessing.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/wrappers/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/wrappers/blocked_well_mp.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/multi_processing/wrappers/mesh_mp.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/ab_toolbox.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/base.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/box_utilities.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/class_dict.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/consolidation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/data/build.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/data/properties.json +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/dataframe.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/exceptions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/factors.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/fine_coarse.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/grid_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/intersection.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/keyword_files.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/load_data.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/point_inclusion.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/random_seed.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/read_nexus_fault.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/relperm.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/simple_lines.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/time.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/trademark.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/transmission.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/uuid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/vdb.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/vector_utilities.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/volume.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/wellspec_keywords.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/write_data.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/write_hdf5.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/xml_et.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/xml_namespaces.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/olio/zmap_reader.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/_utils.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/boundary_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/boundary_feature_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/earth_model_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/fault_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/fluid_boundary_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/frontier_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/generic_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/genetic_boundary_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/geobody_boundary_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/geobody_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/geobody_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/geologic_unit_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/horizon_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/organization_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/rock_fluid_unit_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/structural_organization_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/tectonic_boundary_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/wellbore_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/organize/wellbore_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/_collection_add_part.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/_collection_create_xml.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/_collection_support.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/_property.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/attribute_property_set.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/grid_property_collection.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/property_collection.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/property_common.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/property_kind.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/string_lookup.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/well_interval_property.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/well_interval_property_collection.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/well_log.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/property/well_log_collection.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_add_ab_properties.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_add_surfaces.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_grid_from_cp.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_import_nexus.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_import_vdb_all_grids.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/rq_import/_import_vdb_ensemble.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_binary_contact_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_geologic_unit_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_strata_common.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_stratigraphic_column.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_stratigraphic_column_rank.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_stratigraphic_unit_feature.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/strata/_stratigraphic_unit_interpretation.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_base_surface.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_combined_surface.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_mesh.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_pointset.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_tri_mesh_stencil.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/surface/_triangulated_patch.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_any_time_series.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_from_nexus_summary.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_functions.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_geologic_time_series.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_time_duration.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/time_series/_time_series.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/_hexa_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/_prism_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/_pyramid_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/_tetra_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/unstructured/_unstructured_grid.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/weights_and_measures/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/weights_and_measures/nexus_units.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/weights_and_measures/weights_and_measures.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/__init__.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_blocked_well.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_deviation_survey.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_md_datum.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_trajectory.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_wellbore_frame.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_wellbore_marker.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/_wellbore_marker_frame.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/blocked_well_frame.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/well_object_funcs.py +0 -0
- {resqpy-5.0.0 → resqpy-5.1.0}/resqpy/well/well_utils.py +0 -0
@@ -880,7 +880,8 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
880
880
|
return_properties = None,
|
881
881
|
raw_bisector = False,
|
882
882
|
n_batches = 20,
|
883
|
-
packed_bisectors = False
|
883
|
+
packed_bisectors = False,
|
884
|
+
patch_indices = None):
|
884
885
|
"""Returns a grid connection set containing those cell faces which are deemed to represent the surface.
|
885
886
|
|
886
887
|
argumants:
|
@@ -916,11 +917,14 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
916
917
|
threading allows some parallelism between the batches)
|
917
918
|
packed_bisectors (bool, default False): if True and return properties include 'grid bisector' then
|
918
919
|
non curtain bisectors are returned in packed form
|
920
|
+
patch_indices (numpy int array, optional): if present, an array over grid cells indicating which
|
921
|
+
patch of surface is applicable in terms of a bisector, for each cell
|
919
922
|
|
920
923
|
returns:
|
921
924
|
gcs or (gcs, gcs_props)
|
922
925
|
where gcs is a new GridConnectionSet with a single feature, not yet written to hdf5 nor xml created;
|
923
|
-
gcs_props is a dictionary mapping from requested return_properties string to numpy array
|
926
|
+
gcs_props is a dictionary mapping from requested return_properties string to numpy array (or tuple
|
927
|
+
of numpy array and curtain bool in the case of grid bisector)
|
924
928
|
|
925
929
|
notes:
|
926
930
|
this function is designed for aligned regular grids only;
|
@@ -929,7 +933,9 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
929
933
|
no trimming of the surface is carried out here: for computational efficiency, it is recommended
|
930
934
|
to trim first;
|
931
935
|
organisational objects for the feature are created if needed;
|
932
|
-
if the offset return property is requested, the implicit units will be the z units of the grid's crs
|
936
|
+
if the offset return property is requested, the implicit units will be the z units of the grid's crs;
|
937
|
+
if patch_indices is present and grid bisectors are being returned, a composite bisector array is returned
|
938
|
+
with elements set from individual bisectors for each patch of surface
|
933
939
|
"""
|
934
940
|
|
935
941
|
assert isinstance(grid, grr.RegularGrid)
|
@@ -959,7 +965,10 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
959
965
|
return_flange_bool = "flange bool" in return_properties
|
960
966
|
if return_flange_bool:
|
961
967
|
return_triangles = True
|
962
|
-
|
968
|
+
patchwork = return_bisector and patch_indices is not None
|
969
|
+
if patchwork:
|
970
|
+
return_triangles = True # triangle numbers are used to infer patch index
|
971
|
+
assert patch_indices.shape == tuple(grid.extent_kji)
|
963
972
|
if title is None:
|
964
973
|
title = name
|
965
974
|
|
@@ -1165,7 +1174,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1165
1174
|
k_faces_kji0 = k_faces_kji0,
|
1166
1175
|
j_faces_kji0 = j_faces_kji0,
|
1167
1176
|
i_faces_kji0 = i_faces_kji0,
|
1168
|
-
remove_duplicates =
|
1177
|
+
remove_duplicates = not patchwork,
|
1169
1178
|
k_properties = k_props,
|
1170
1179
|
j_properties = j_props,
|
1171
1180
|
i_properties = i_props,
|
@@ -1176,6 +1185,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1176
1185
|
# log.debug('finished coversion to gcs')
|
1177
1186
|
|
1178
1187
|
# NB. following assumes faces have been added to gcs in a particular order!
|
1188
|
+
all_tris = None
|
1179
1189
|
if return_triangles:
|
1180
1190
|
# log.debug('preparing triangles array')
|
1181
1191
|
k_triangles = np.empty((0,), dtype = np.int32) if k_props is None else k_props.pop(0)
|
@@ -1186,6 +1196,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1186
1196
|
assert all_tris.shape == (gcs.count,)
|
1187
1197
|
|
1188
1198
|
# NB. following assumes faces have been added to gcs in a particular order!
|
1199
|
+
all_depths = None
|
1189
1200
|
if return_depths:
|
1190
1201
|
# log.debug('preparing depths array')
|
1191
1202
|
k_depths = np.empty((0,), dtype = np.float64) if k_props is None else k_props.pop(0)
|
@@ -1196,6 +1207,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1196
1207
|
assert all_depths.shape == (gcs.count,)
|
1197
1208
|
|
1198
1209
|
# NB. following assumes faces have been added to gcs in a particular order!
|
1210
|
+
all_offsets = None
|
1199
1211
|
if return_offsets:
|
1200
1212
|
# log.debug('preparing offsets array')
|
1201
1213
|
k_offsets = np.empty((0,), dtype = np.float64) if k_props is None else k_props[0]
|
@@ -1205,6 +1217,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1205
1217
|
# log.debug(f'gcs count: {gcs.count}; all offsets shape: {all_offsets.shape}')
|
1206
1218
|
assert all_offsets.shape == (gcs.count,)
|
1207
1219
|
|
1220
|
+
all_flange = None
|
1208
1221
|
if return_flange_bool:
|
1209
1222
|
# log.debug('preparing flange array')
|
1210
1223
|
flange_bool_uuid = surface.model.uuid(title = "flange bool",
|
@@ -1217,8 +1230,9 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1217
1230
|
assert all_flange.shape == (gcs.count,)
|
1218
1231
|
|
1219
1232
|
# note: following is a grid cells property, not a gcs property
|
1233
|
+
bisector = None
|
1220
1234
|
if return_bisector:
|
1221
|
-
if is_curtain:
|
1235
|
+
if is_curtain and not patchwork:
|
1222
1236
|
log.debug("preparing columns bisector")
|
1223
1237
|
if j_faces_kji0 is None:
|
1224
1238
|
j_faces_ji0 = np.empty((0, 2), dtype = np.int32)
|
@@ -1230,8 +1244,51 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1230
1244
|
i_faces_ji0 = i_faces_kji0[:, 1:]
|
1231
1245
|
bisector = column_bisector_from_face_indices((grid.nj, grid.ni), j_faces_ji0, i_faces_ji0)
|
1232
1246
|
# log.debug('finished preparing columns bisector')
|
1247
|
+
elif patchwork:
|
1248
|
+
n_patches = surface.number_of_patches()
|
1249
|
+
nkf = len(k_faces_kji0)
|
1250
|
+
njf = len(j_faces_kji0)
|
1251
|
+
nif = len(i_faces_kji0)
|
1252
|
+
# fetch patch indices for triangle hits
|
1253
|
+
assert all_tris is not None and len(all_tris) == nkf + njf + nif
|
1254
|
+
patch_indices_k = surface.patch_indices_for_triangle_indices(all_tris[:nkf])
|
1255
|
+
patch_indices_j = surface.patch_indices_for_triangle_indices(all_tris[nkf:nkf + njf])
|
1256
|
+
patch_indices_i = surface.patch_indices_for_triangle_indices(all_tris[nkf + njf:])
|
1257
|
+
# add extra dimension to bisector array (at axis 0) for patches
|
1258
|
+
pb_shape = tuple([n_patches] + list(grid.extent_kji))
|
1259
|
+
if packed_bisectors:
|
1260
|
+
bisector = np.ones(_shape_packed(grid.extent_kji), dtype = np.uint8)
|
1261
|
+
else:
|
1262
|
+
bisector = np.ones(tuple(grid.extent_kji), dtype = np.bool_)
|
1263
|
+
# populate 4D bisector with an axis zero slice for each patch
|
1264
|
+
for patch in range(n_patches):
|
1265
|
+
mask = (patch_indices == patch)
|
1266
|
+
if np.count_nonzero(mask) == 0:
|
1267
|
+
log.warning(f'patch {patch} of surface {surface.title} is not applicable to any cells in grid')
|
1268
|
+
continue
|
1269
|
+
if packed_bisectors:
|
1270
|
+
mask = np.packbits(mask, axis = -1)
|
1271
|
+
patch_bisector, is_curtain = \
|
1272
|
+
packed_bisector_from_face_indices(tuple(grid.extent_kji),
|
1273
|
+
k_faces_kji0[(patch_indices_k == patch).astype(bool)],
|
1274
|
+
j_faces_kji0[(patch_indices_j == patch).astype(bool)],
|
1275
|
+
i_faces_kji0[(patch_indices_i == patch).astype(bool)],
|
1276
|
+
raw_bisector)
|
1277
|
+
bisector = np.bitwise_or(np.bitwise_and(mask, patch_bisector), bisector)
|
1278
|
+
else:
|
1279
|
+
patch_bisector, is_curtain = \
|
1280
|
+
bisector_from_face_indices(tuple(grid.extent_kji),
|
1281
|
+
k_faces_kji0[(patch_indices_k == patch).astype(bool)],
|
1282
|
+
j_faces_kji0[(patch_indices_j == patch).astype(bool)],
|
1283
|
+
i_faces_kji0[(patch_indices_i == patch).astype(bool)],
|
1284
|
+
raw_bisector)
|
1285
|
+
bisector[mask] = patch_bisector[mask]
|
1286
|
+
if is_curtain:
|
1287
|
+
# TODO: downgrade following to debug once downstream functionality tested
|
1288
|
+
log.warning(f'ignoring curtain nature of bisector for patch {patch} of surface: {surface.title}')
|
1289
|
+
is_curtain = False
|
1233
1290
|
else:
|
1234
|
-
log.debug("preparing cells bisector")
|
1291
|
+
log.debug("preparing singlular cells bisector")
|
1235
1292
|
if ((k_faces_kji0 is None or len(k_faces_kji0) == 0) and
|
1236
1293
|
(j_faces_kji0 is None or len(j_faces_kji0) == 0) and (i_faces_kji0 is None or len(i_faces_kji0) == 0)):
|
1237
1294
|
bisector = np.ones((grid.nj, grid.ni), dtype = bool)
|
@@ -1249,6 +1306,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1249
1306
|
bisector = bisector[0] # reduce to a columns property
|
1250
1307
|
|
1251
1308
|
# note: following is a grid cells property, not a gcs property
|
1309
|
+
shadow = None
|
1252
1310
|
if return_shadow:
|
1253
1311
|
log.debug("preparing cells shadow")
|
1254
1312
|
shadow = shadow_from_face_indices(tuple(grid.extent_kji), k_faces_kji0)
|
@@ -1261,7 +1319,7 @@ def find_faces_to_represent_surface_regular_optimised(grid,
|
|
1261
1319
|
# if returning properties, construct dictionary
|
1262
1320
|
if return_properties:
|
1263
1321
|
props_dict = {}
|
1264
|
-
if
|
1322
|
+
if 'triangle' in return_properties:
|
1265
1323
|
props_dict["triangle"] = all_tris
|
1266
1324
|
if return_depths:
|
1267
1325
|
props_dict["depth"] = all_depths
|
@@ -1363,7 +1421,7 @@ def bisector_from_faces( # type: ignore
|
|
1363
1421
|
- the face sets must form a single 'sealed' cut of the grid (eg. not waving in and out of the grid)
|
1364
1422
|
- any 'boxed in' parts of the grid (completely enclosed by bisecting faces) will be consistently
|
1365
1423
|
assigned to either the True or False part
|
1366
|
-
- this function is DEPRECATED,
|
1424
|
+
- this function is DEPRECATED, use newer indices based approach instead: bisector_from_face_indices()
|
1367
1425
|
"""
|
1368
1426
|
warnings.warn('DEPRECATED: grid_surface.bisector_from_faces() function; use bisector_from_face_indices() instead')
|
1369
1427
|
assert len(grid_extent_kji) == 3
|
@@ -1408,10 +1466,13 @@ def bisector_from_faces( # type: ignore
|
|
1408
1466
|
# check all array elements are not the same
|
1409
1467
|
true_count = np.count_nonzero(array)
|
1410
1468
|
cell_count = array.size
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1469
|
+
if 0 < true_count < cell_count:
|
1470
|
+
# negate the array if it minimises the mean k and determine if the surface is a curtain
|
1471
|
+
is_curtain = _shallow_or_curtain(array, true_count, raw_bisector)
|
1472
|
+
else:
|
1473
|
+
assert raw_bisector, 'face set for surface is leaky or empty (surface does not intersect grid)'
|
1474
|
+
log.error('face set for surface is leaky or empty (surface does not intersect grid)')
|
1475
|
+
is_curtain = False
|
1415
1476
|
|
1416
1477
|
return array, is_curtain
|
1417
1478
|
|
@@ -1482,10 +1543,13 @@ def bisector_from_face_indices( # type: ignore
|
|
1482
1543
|
# check all array elements are not the same
|
1483
1544
|
true_count = np.count_nonzero(array)
|
1484
1545
|
cell_count = array.size
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1546
|
+
if 0 < true_count < cell_count:
|
1547
|
+
# negate the array if it minimises the mean k and determine if the surface is a curtain
|
1548
|
+
is_curtain = _shallow_or_curtain(array, true_count, raw_bisector)
|
1549
|
+
else:
|
1550
|
+
assert raw_bisector, 'face set for surface is leaky or empty (surface does not intersect grid)'
|
1551
|
+
log.error('face set for surface is leaky or empty (surface does not intersect grid)')
|
1552
|
+
is_curtain = False
|
1489
1553
|
|
1490
1554
|
return array, is_curtain
|
1491
1555
|
|
@@ -1572,12 +1636,14 @@ def packed_bisector_from_face_indices( # type: ignore
|
|
1572
1636
|
else:
|
1573
1637
|
true_count = _bitwise_count_njit(array) # note: will usually include some padding bits, so not so true!
|
1574
1638
|
cell_count = np.prod(grid_extent_kji)
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1639
|
+
if 0 < true_count < cell_count:
|
1640
|
+
# negate the array if it minimises the mean k and determine if the surface is a curtain
|
1641
|
+
# TODO: switch to _packed_shallow_or_curtain_temp_bitwise_count() when numba supports np.bitwise_count()
|
1642
|
+
is_curtain = _packed_shallow_or_curtain_temp_bitwise_count(array, true_count, raw_bisector)
|
1643
|
+
else:
|
1644
|
+
assert raw_bisector, 'face set for surface is leaky or empty (surface does not intersect grid)'
|
1645
|
+
log.error('face set for surface is leaky or empty (surface does not intersect grid)')
|
1646
|
+
is_curtain = False
|
1581
1647
|
|
1582
1648
|
return array, is_curtain
|
1583
1649
|
|
@@ -2227,12 +2293,12 @@ def get_boundary_from_indices( # type: ignore
|
|
2227
2293
|
k_faces_kji0: Union[np.ndarray, None], j_faces_kji0: Union[np.ndarray, None],
|
2228
2294
|
i_faces_kji0: Union[np.ndarray, None], grid_extent_kji: Tuple[int, int, int]) -> np.ndarray:
|
2229
2295
|
"""Return python protocol box containing indices"""
|
2230
|
-
k_min_kji0 = None if k_faces_kji0 is None else np.min(k_faces_kji0, axis = 0)
|
2231
|
-
k_max_kji0 = None if k_faces_kji0 is None else np.max(k_faces_kji0, axis = 0)
|
2232
|
-
j_min_kji0 = None if j_faces_kji0 is None else np.min(j_faces_kji0, axis = 0)
|
2233
|
-
j_max_kji0 = None if j_faces_kji0 is None else np.max(j_faces_kji0, axis = 0)
|
2234
|
-
i_min_kji0 = None if i_faces_kji0 is None else np.min(i_faces_kji0, axis = 0)
|
2235
|
-
i_max_kji0 = None if i_faces_kji0 is None else np.max(i_faces_kji0, axis = 0)
|
2296
|
+
k_min_kji0 = None if (k_faces_kji0 is None or k_faces_kji0.size == 0) else np.min(k_faces_kji0, axis = 0)
|
2297
|
+
k_max_kji0 = None if (k_faces_kji0 is None or k_faces_kji0.size == 0) else np.max(k_faces_kji0, axis = 0)
|
2298
|
+
j_min_kji0 = None if (j_faces_kji0 is None or j_faces_kji0.size == 0) else np.min(j_faces_kji0, axis = 0)
|
2299
|
+
j_max_kji0 = None if (j_faces_kji0 is None or j_faces_kji0.size == 0) else np.max(j_faces_kji0, axis = 0)
|
2300
|
+
i_min_kji0 = None if (i_faces_kji0 is None or i_faces_kji0.size == 0) else np.min(i_faces_kji0, axis = 0)
|
2301
|
+
i_max_kji0 = None if (i_faces_kji0 is None or i_faces_kji0.size == 0) else np.max(i_faces_kji0, axis = 0)
|
2236
2302
|
box = np.empty((2, 3), dtype = np.int32)
|
2237
2303
|
box[0, :] = grid_extent_kji
|
2238
2304
|
box[1, :] = -1
|
@@ -2100,6 +2100,11 @@ class Model():
|
|
2100
2100
|
if other_model is self:
|
2101
2101
|
return part
|
2102
2102
|
assert part is not None
|
2103
|
+
# check whether already existing in this model
|
2104
|
+
if part in self.parts_forest.keys():
|
2105
|
+
return part
|
2106
|
+
if m_c._type_of_part(other_model, part) == 'obj_EpcExternalPartReference':
|
2107
|
+
return None
|
2103
2108
|
if realization is not None:
|
2104
2109
|
assert isinstance(realization, int) and realization >= 0
|
2105
2110
|
if force:
|
@@ -2110,13 +2115,6 @@ class Model():
|
|
2110
2115
|
self_h5_file_name = self.h5_file_name(file_must_exist = False)
|
2111
2116
|
hdf5_copy_needed = not os.path.samefile(self_h5_file_name, other_h5_file_name)
|
2112
2117
|
|
2113
|
-
# check whether already existing in this model
|
2114
|
-
if part in self.parts_forest.keys():
|
2115
|
-
return part
|
2116
|
-
|
2117
|
-
if m_c._type_of_part(other_model, part) == 'obj_EpcExternalPartReference':
|
2118
|
-
return None
|
2119
|
-
|
2120
2118
|
return m_f._copy_part_from_other_model(self,
|
2121
2119
|
other_model,
|
2122
2120
|
part,
|
@@ -4,8 +4,10 @@ import logging
|
|
4
4
|
|
5
5
|
log = logging.getLogger(__name__)
|
6
6
|
|
7
|
+
import os
|
7
8
|
import numpy as np
|
8
9
|
import uuid
|
10
|
+
import ast
|
9
11
|
from typing import Tuple, Union, List, Optional, Callable
|
10
12
|
from pathlib import Path
|
11
13
|
from uuid import UUID
|
@@ -18,33 +20,38 @@ import resqpy.surface as rqs
|
|
18
20
|
import resqpy.olio.uuid as bu
|
19
21
|
|
20
22
|
|
21
|
-
def find_faces_to_represent_surface_regular_wrapper(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
23
|
+
def find_faces_to_represent_surface_regular_wrapper(
|
24
|
+
index: int,
|
25
|
+
parent_tmp_dir: str,
|
26
|
+
use_index_as_realisation: bool,
|
27
|
+
grid_epc: str,
|
28
|
+
grid_uuid: Union[UUID, str],
|
29
|
+
surface_epc: str,
|
30
|
+
surface_uuid: Union[UUID, str],
|
31
|
+
name: str,
|
32
|
+
title: Optional[str] = None,
|
33
|
+
agitate: bool = False,
|
34
|
+
random_agitation: bool = False,
|
35
|
+
feature_type: str = 'fault',
|
36
|
+
trimmed: bool = False,
|
37
|
+
is_curtain = False,
|
38
|
+
extend_fault_representation: bool = False,
|
39
|
+
flange_inner_ring: bool = False,
|
40
|
+
saucer_parameter: Optional[float] = None,
|
41
|
+
retriangulate: bool = False,
|
42
|
+
related_uuid: Optional[Union[UUID, str]] = None,
|
43
|
+
progress_fn: Optional[Callable] = None,
|
44
|
+
extra_metadata = None,
|
45
|
+
return_properties: Optional[List[str]] = None,
|
46
|
+
raw_bisector: bool = False,
|
47
|
+
use_pack: bool = False,
|
48
|
+
flange_radius: Optional[float] = None,
|
49
|
+
reorient: bool = True,
|
50
|
+
n_threads: int = 20,
|
51
|
+
patchwork: bool = False,
|
52
|
+
grid_patching_property_uuid: Optional[Union[UUID, str]] = None,
|
53
|
+
surface_patching_property_uuid: Optional[Union[UUID, str]] = None) -> \
|
54
|
+
Tuple[int, bool, str, List[Union[UUID, str]]]:
|
48
55
|
"""Multiprocessing wrapper function of find_faces_to_represent_surface_regular_optimised.
|
49
56
|
|
50
57
|
arguments:
|
@@ -98,8 +105,17 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
98
105
|
flange_radius (float, optional): the radial distance to use for outer flange extension points; if None,
|
99
106
|
a large value will be calculated from the grid size; units are xy units of grid crs
|
100
107
|
reorient (bool, default True): if True, the points are reoriented to minimise the
|
101
|
-
|
108
|
+
z range prior to retriangulation (ie. z axis is approximate normal to plane of points), to enhace the triangulation
|
102
109
|
n_threads (int, default 20): the number of parallel threads to use in numba points in triangles function
|
110
|
+
patchwork (bool, default False): if True and grid bisector is included in return properties, a compostite
|
111
|
+
bisector is generated, based on individual ones for each patch of the surface; the following two
|
112
|
+
arguments must be set if patchwork is True
|
113
|
+
grid_patching_property_uuid (uuid, optional): required if patchwork is True, the uuid of a discrete or
|
114
|
+
categorical cells property on the grid which will be used to determine which patch of the surface is
|
115
|
+
relevant to a cell
|
116
|
+
surface_patching_property_uuid (uuid, optional): required if patchwork is True, the uuid of a discrete or
|
117
|
+
categorical property on the patches of the surface, identifying the value of the grid patching property
|
118
|
+
that each patch relates to
|
103
119
|
|
104
120
|
returns:
|
105
121
|
Tuple containing:
|
@@ -109,18 +125,15 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
109
125
|
- uuid_list (List[str]): list of UUIDs of relevant objects
|
110
126
|
|
111
127
|
notes:
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
the saucer_parameter is
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
+ve angles result in the shift being in the direction of the -ve z hemisphere; -ve angles result in
|
122
|
-
the shift being in the +ve z hemisphere; in either case the direction of the shift is perpendicular
|
123
|
-
to the average plane of the original points
|
128
|
+
- use this function as argument to the multiprocessing function; it will create a new model that is saved
|
129
|
+
in a temporary epc file and returns the required values, which are used in the multiprocessing function to
|
130
|
+
recombine all the objects into a single epc file
|
131
|
+
- the saucer_parameter is between -90.0 and 90.0 and is interpreted as an angle to apply out of
|
132
|
+
the plane of the original points, to give a simple saucer shape;
|
133
|
+
+ve angles result in the shift being in the direction of the -ve z hemisphere; -ve angles result in
|
134
|
+
the shift being in the +ve z hemisphere; in either case the direction of the shift is perpendicular
|
135
|
+
to the average plane of the original points
|
136
|
+
- patchwork is not compatible with re-triangulation
|
124
137
|
"""
|
125
138
|
tmp_dir = Path(parent_tmp_dir) / f"{uuid.uuid4()}"
|
126
139
|
tmp_dir.mkdir(parents = True, exist_ok = True)
|
@@ -149,11 +162,18 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
149
162
|
flange_radius = 5.0 * np.sum(np.array(grid.extent_kji, dtype = float) * np.array(grid.aligned_dxyz()))
|
150
163
|
s_model = rq.Model(surface_epc, quiet = True)
|
151
164
|
model.copy_uuid_from_other_model(s_model, uuid = str(surface_uuid))
|
165
|
+
if surface_patching_property_uuid is not None:
|
166
|
+
model.copy_uuid_from_other_model(s_model, uuid = surface_patching_property_uuid)
|
167
|
+
uuid_list.append(surface_patching_property_uuid)
|
152
168
|
repr_type = model.type_of_part(model.part(uuid = surface_uuid), strip_obj = True)
|
153
169
|
assert repr_type in ['TriangulatedSetRepresentation', 'PointSetRepresentation']
|
170
|
+
assert repr_type == 'TriangulatedSetRepresentation' or not patchwork, \
|
171
|
+
'patchwork only implemented for triangulated set surfaces'
|
172
|
+
|
154
173
|
extended = False
|
155
174
|
retriangulated = False
|
156
175
|
flange_bool = None
|
176
|
+
|
157
177
|
if repr_type == 'PointSetRepresentation':
|
158
178
|
# trim pointset to grid xyz box
|
159
179
|
pset = rqs.PointSet(model, uuid = surface_uuid)
|
@@ -197,15 +217,22 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
197
217
|
surf_title = surface.title
|
198
218
|
assert surf_title
|
199
219
|
surface.change_crs(grid.crs)
|
220
|
+
normal_vector = None
|
221
|
+
if reorient:
|
222
|
+
normal_vector = surface.normal()
|
223
|
+
if patchwork: # disable trimming as whole patches could be trimmed out, changing the patch indexing from that expected
|
224
|
+
trimmed = True
|
200
225
|
if not trimmed and surface.triangle_count() > 100:
|
201
226
|
if not surf_title.endswith('trimmed'):
|
202
227
|
surf_title += ' trimmed'
|
203
228
|
trimmed_surf = rqs.Surface(model, crs_uuid = grid.crs.uuid, title = surf_title)
|
204
229
|
# trimmed_surf.set_to_trimmed_surface(surf, xyz_box = xyz_box, xy_polygon = parent_seg.polygon)
|
205
230
|
trimmed_surf.set_to_trimmed_surface(surface, xyz_box = grid.xyz_box(local = True))
|
231
|
+
trimmed_surf.extra_metadata = surface.extra_metadata
|
206
232
|
surface = trimmed_surf
|
207
233
|
trimmed = True
|
208
234
|
if (extend_fault_representation and not extended) or (retriangulate and not retriangulated):
|
235
|
+
assert not patchwork, 'extension or re-triangulation are not compatible with patchwork'
|
209
236
|
_, p = surface.triangles_and_points()
|
210
237
|
pset = rqs.PointSet(model, points_array = p, crs_uuid = grid.crs.uuid, title = surf_title)
|
211
238
|
if extend_fault_representation and not surf_title.endswith('extended'):
|
@@ -218,7 +245,8 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
218
245
|
flange_inner_ring = flange_inner_ring,
|
219
246
|
saucer_parameter = saucer_parameter,
|
220
247
|
flange_radial_distance = flange_radius,
|
221
|
-
make_clockwise = False
|
248
|
+
make_clockwise = False,
|
249
|
+
normal_vector = normal_vector)
|
222
250
|
del pset
|
223
251
|
extended = extend_fault_representation
|
224
252
|
retriangulated = True
|
@@ -242,7 +270,23 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
242
270
|
discrete = True,
|
243
271
|
dtype = np.uint8)
|
244
272
|
uuid_list.append(flange_p.uuid)
|
245
|
-
|
273
|
+
|
274
|
+
if not patchwork:
|
275
|
+
uuid_list.append(surface_uuid)
|
276
|
+
|
277
|
+
patch_indices = None
|
278
|
+
if patchwork: # generate a patch indices array over grid cells based on supplied patching properties
|
279
|
+
assert grid_patching_property_uuid is not None and surface_patching_property_uuid is not None
|
280
|
+
g_patching_array = rqp.Property(g_model, uuid = grid_patching_property_uuid).array_ref()
|
281
|
+
assert g_patching_array.shape == tuple(grid.extent_kji)
|
282
|
+
s_patches_array = rqp.Property(model, uuid = surface_patching_property_uuid).array_ref()
|
283
|
+
patch_count = surface.number_of_patches()
|
284
|
+
assert s_patches_array.shape == (patch_count,)
|
285
|
+
p_dtype = (np.int8 if s_patches_array.shape[0] < 128 else np.int32)
|
286
|
+
patch_indices = np.full(g_patching_array.shape, -1, dtype = p_dtype)
|
287
|
+
for patch in range(patch_count):
|
288
|
+
gp = s_patches_array[patch]
|
289
|
+
patch_indices[(g_patching_array == gp).astype(bool)] = patch
|
246
290
|
|
247
291
|
returns = rqgs.find_faces_to_represent_surface_regular_optimised(grid,
|
248
292
|
surface,
|
@@ -256,7 +300,8 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
256
300
|
return_properties,
|
257
301
|
raw_bisector = raw_bisector,
|
258
302
|
n_batches = n_threads,
|
259
|
-
packed_bisectors = use_pack
|
303
|
+
packed_bisectors = use_pack,
|
304
|
+
patch_indices = patch_indices)
|
260
305
|
|
261
306
|
success = False
|
262
307
|
|
@@ -286,6 +331,7 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
286
331
|
|
287
332
|
if success and return_properties is not None and len(return_properties):
|
288
333
|
log.debug(f'{name} requested properties: {return_properties}')
|
334
|
+
assert isinstance(returns, tuple)
|
289
335
|
properties = returns[1]
|
290
336
|
realisation = index if use_index_as_realisation else None
|
291
337
|
property_collection = rqp.PropertyCollection(support = gcs)
|
@@ -346,6 +392,7 @@ def find_faces_to_represent_surface_regular_wrapper(index: int,
|
|
346
392
|
if grid_pc is None:
|
347
393
|
grid_pc = rqp.PropertyCollection()
|
348
394
|
grid_pc.set_support(support = grid)
|
395
|
+
assert array.ndim == (2 if is_curtain else 3)
|
349
396
|
grid_pc.add_cached_array_to_imported_list(array,
|
350
397
|
f"from find_faces function for {surface.title}",
|
351
398
|
f'{surface.title} {p_name}',
|
@@ -48,7 +48,7 @@ def _dt_scipy(points: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
|
|
48
48
|
|
49
49
|
|
50
50
|
def _dt_simple(po, plot_fn = None, progress_fn = None, container_size_factor = None):
|
51
|
-
# returns
|
51
|
+
# returns Delaunay triangulation of po and list of hull point indices, using a simple algorithm
|
52
52
|
|
53
53
|
def flip(ei):
|
54
54
|
nonlocal fm, e, t, te, p, nt, p_i, ne
|
@@ -234,7 +234,7 @@ def _dt_simple(po, plot_fn = None, progress_fn = None, container_size_factor = N
|
|
234
234
|
|
235
235
|
|
236
236
|
def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_size_factor = 100.0, return_hull = False):
|
237
|
-
"""Returns the
|
237
|
+
"""Returns the Delaunay Triangulation of 2D point set p.
|
238
238
|
|
239
239
|
arguments:
|
240
240
|
p (numpy float array of shape (N, 2): the x,y coordinates of the points
|
@@ -253,7 +253,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz
|
|
253
253
|
|
254
254
|
returns:
|
255
255
|
numpy int array of shape (M, 3) - being the indices into the first axis of p of the 3 points
|
256
|
-
per triangle in the
|
256
|
+
per triangle in the Delaunay Triangulation - and if return_hull is True, another int array
|
257
257
|
of shape (B,) - being indices into p of the clockwise ordered points on the boundary of
|
258
258
|
the triangulation
|
259
259
|
|
@@ -261,7 +261,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz
|
|
261
261
|
the plot_fn, progress_fn and container_size_factor arguments are only used by the 'simple' algorithm;
|
262
262
|
if points p are 3D, the projection onto the xy plane is used for the triangulation
|
263
263
|
"""
|
264
|
-
assert p.ndim == 2 and p.shape[1] >= 2, 'bad points shape for 2D
|
264
|
+
assert p.ndim == 2 and p.shape[1] >= 2, 'bad points shape for 2D Delaunay Triangulation'
|
265
265
|
|
266
266
|
if not algorithm:
|
267
267
|
algorithm = 'scipy'
|
@@ -274,7 +274,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz
|
|
274
274
|
progress_fn = progress_fn,
|
275
275
|
container_size_factor = container_size_factor)
|
276
276
|
else:
|
277
|
-
raise Exception(f'unrecognised
|
277
|
+
raise Exception(f'unrecognised Delaunay Triangulation algorithm name: {algorithm}')
|
278
278
|
|
279
279
|
assert tri.ndim == 2 and tri.shape[1] == 3
|
280
280
|
|
@@ -304,11 +304,11 @@ def ccc(p1, p2, p3):
|
|
304
304
|
|
305
305
|
|
306
306
|
def voronoi(p, t, b, aoi: rql.Polyline):
|
307
|
-
"""Returns dual Voronoi diagram for a
|
307
|
+
"""Returns dual Voronoi diagram for a Delaunay triangulation.
|
308
308
|
|
309
309
|
arguments:
|
310
|
-
p (numpy float array of shape (N, 2)): seed points used in the
|
311
|
-
t (numpy int array of shape (M, 3)): the
|
310
|
+
p (numpy float array of shape (N, 2)): seed points used in the Delaunay triangulation
|
311
|
+
t (numpy int array of shape (M, 3)): the Delaunay triangulation of p as returned by dt()
|
312
312
|
b (numpy int array of shape (B,)): clockwise sorted list of indices into p of the boundary
|
313
313
|
points of the triangulation t
|
314
314
|
aoi (lines.Polyline): area of interest; a closed clockwise polyline that must strictly contain
|
@@ -329,7 +329,7 @@ def voronoi(p, t, b, aoi: rql.Polyline):
|
|
329
329
|
|
330
330
|
# this code assumes that the Voronoi polygon for a seed point visits the circumcentres of
|
331
331
|
# all the triangles that make use of the point – currently understood to be always the case
|
332
|
-
# for a
|
332
|
+
# for a Delaunay triangulation
|
333
333
|
|
334
334
|
def __aoi_intervening_nodes(aoi_count, c_count, seg_a, seg_c):
|
335
335
|
nodes = []
|
@@ -582,7 +582,7 @@ def voronoi(p, t, b, aoi: rql.Polyline):
|
|
582
582
|
|
583
583
|
# check for concavities in hull
|
584
584
|
if not hull.is_convex():
|
585
|
-
log.warning('
|
585
|
+
log.warning('Delaunay triangulation is not convex; Voronoi diagram construction might fail')
|
586
586
|
|
587
587
|
# compute circumcircle centres
|
588
588
|
c = np.zeros((t.shape[0], 2))
|
@@ -750,7 +750,7 @@ def reorient(points, rough = True, max_dip = None, use_linalg = True, sample = 5
|
|
750
750
|
notes:
|
751
751
|
the original points array is not modified by this function;
|
752
752
|
implicit xy & z units for points are assumed to be the same;
|
753
|
-
the function may typically be called prior to the
|
753
|
+
the function may typically be called prior to the Delaunay triangulation, which uses an xy projection to
|
754
754
|
determine the triangulation;
|
755
755
|
the numpy linear algebra option seems to be memory intensive, not recommended;
|
756
756
|
downsampling will occur (for normal vector determination) when the number of points exceeds double that
|
@@ -868,10 +868,11 @@ def surrounding_xy_ring(p,
|
|
868
868
|
being an angle to determine a z offset for the ring(s); a +ve angle results in a -ve z shift
|
869
869
|
|
870
870
|
returns:
|
871
|
-
numpy float array
|
872
|
-
|
873
|
-
|
874
|
-
|
871
|
+
(numpy float array, float) pair:
|
872
|
+
- numpy float array of shape (N, 3) being xyz points in surrounding ring(s); z is set constant to
|
873
|
+
mean value of z in p (optionally adjussted based on saucer_angle);
|
874
|
+
N is count if inner_ring is False, 3 * count if True
|
875
|
+
- radius used for ring of additional points
|
875
876
|
"""
|
876
877
|
|
877
878
|
def make_ring(count, centre, radius, saucer_angle):
|
@@ -509,6 +509,8 @@ def _supporting_shape_surface(support, indexable_element):
|
|
509
509
|
shape_list = [support.triangle_count()]
|
510
510
|
elif indexable_element == 'nodes':
|
511
511
|
shape_list = [support.node_count()]
|
512
|
+
elif indexable_element == 'patches':
|
513
|
+
shape_list = [len(support.patch_list)]
|
512
514
|
return shape_list
|
513
515
|
|
514
516
|
|