From 0967e576e3277a65ec3fb7fb2f2571ae44e0a633 Mon Sep 17 00:00:00 2001 From: Sigurd Pettersen Date: Tue, 13 Feb 2024 12:38:22 +0100 Subject: [PATCH 01/45] Draft definition of Webviz/RI proto file --- GrpcInterface/GrpcProtos/GridWebviz.proto | 102 ++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 GrpcInterface/GrpcProtos/GridWebviz.proto diff --git a/GrpcInterface/GrpcProtos/GridWebviz.proto b/GrpcInterface/GrpcProtos/GridWebviz.proto new file mode 100644 index 0000000000..abb77d30bd --- /dev/null +++ b/GrpcInterface/GrpcProtos/GridWebviz.proto @@ -0,0 +1,102 @@ +syntax = "proto3"; + +// Will this work if we import only part of the protos? +package rips; + +service GridWebviz +{ + rpc getGridSurface(GetGridSurfaceRequest) returns (GetGridSurfaceResponse); + rpc cutAlongPolyline(CutAlongPolylineRequest) returns (CutAlongPolylineResponse); +} + + +message Vec2d +{ + double x = 1; + double y = 2; +} + +message Vec3d +{ + double x = 1; + double y = 2; + double z = 3; +} + +message IJKIndexFilter +{ + int32 iMin = 1; + int32 iMax = 2; + int32 jMin = 3; + int32 jMax = 4; + int32 kMin = 5; + int32 kMax = 6; +} + +message CellIndexFilter +{ + repeated fixed32 cellIndicesArr = 1; +} + +message PropertyFilter +{ + string propertyFilename = 1; + float valueMin = 2; + float valueMax = 3; +} + +message GridDimensions +{ + uint32 iNum = 1; + uint32 jNum = 2; + uint32 kNum = 3; +} + + +message GetGridSurfaceRequest +{ + string gridFilename = 1; + IJKIndexFilter ijkIndexFilter = 2; + CellIndexFilter cellIndexFilter = 3; + PropertyFilter propertyFilter = 4; +} + +message GetGridSurfaceResponse +{ + repeated float vertexArray = 1; + repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long + repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long + repeated fixed32 propertyIndicesArr = 4; // SHOULD WE HAVE THIS?? Index of property result per quad, numQuads long + GridDimensions gridDimensions = 5; + Vec3d originUtm = 6; +} + + +message CutAlongPolylineRequest +{ + string gridFilename = 1; + IJKIndexFilter ijkIndexFilter = 2; // Should these be present here?? + CellIndexFilter cellIndexFilter = 3; + PropertyFilter propertyFilter = 4; + repeated double fencePolylineUtmXY = 4; +} + +message FenceMeshSection +{ + // U-axis defined by vector from start to end + // V-axis is global Z + repeated float vertexArrayUV = 1; // Plane local UV vertex coordinates + repeated fixed32 polyIndicesArr = 2; + repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long + repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long + repeated fixed32 propertyIndicesArr = 5; // SHOULD WE HAVE THIS?? Index of property result per polygon, numPolygons long + Vec2d startUtmXY = 6; + Vec2d endUtmXY = 7; +} + +message CutAlongPolylineResponse +{ + double originZ = 1; + GridDimensions gridDimensions = 2; + repeated FenceMeshSection feceMeshSections = 3; +} From 242cad41b916c5e3203434b3d85d617b1ee84ae9 Mon Sep 17 00:00:00 2001 From: Sigurd Pettersen Date: Tue, 13 Feb 2024 13:44:25 +0100 Subject: [PATCH 02/45] Update after discussion with MSJ --- GrpcInterface/GrpcProtos/GridWebviz.proto | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/GrpcInterface/GrpcProtos/GridWebviz.proto b/GrpcInterface/GrpcProtos/GridWebviz.proto index abb77d30bd..e95a186e94 100644 --- a/GrpcInterface/GrpcProtos/GridWebviz.proto +++ b/GrpcInterface/GrpcProtos/GridWebviz.proto @@ -40,6 +40,7 @@ message CellIndexFilter message PropertyFilter { + // Timestep ?? string propertyFilename = 1; float valueMin = 2; float valueMax = 3; @@ -52,7 +53,6 @@ message GridDimensions uint32 kNum = 3; } - message GetGridSurfaceRequest { string gridFilename = 1; @@ -66,37 +66,29 @@ message GetGridSurfaceResponse repeated float vertexArray = 1; repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long - repeated fixed32 propertyIndicesArr = 4; // SHOULD WE HAVE THIS?? Index of property result per quad, numQuads long GridDimensions gridDimensions = 5; Vec3d originUtm = 6; } - message CutAlongPolylineRequest { string gridFilename = 1; - IJKIndexFilter ijkIndexFilter = 2; // Should these be present here?? - CellIndexFilter cellIndexFilter = 3; - PropertyFilter propertyFilter = 4; - repeated double fencePolylineUtmXY = 4; + repeated double fencePolylineUtmXY = 2; } message FenceMeshSection { - // U-axis defined by vector from start to end - // V-axis is global Z - repeated float vertexArrayUV = 1; // Plane local UV vertex coordinates + // U-axis defined by vector from start to end, Z is global Z + repeated float vertexArrayUZ = 1; repeated fixed32 polyIndicesArr = 2; repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long - repeated fixed32 propertyIndicesArr = 5; // SHOULD WE HAVE THIS?? Index of property result per polygon, numPolygons long Vec2d startUtmXY = 6; Vec2d endUtmXY = 7; } message CutAlongPolylineResponse { - double originZ = 1; + repeated FenceMeshSection feceMeshSections = 1; GridDimensions gridDimensions = 2; - repeated FenceMeshSection feceMeshSections = 3; } From da0189924117861f512fcd92e7ecae570da909c8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 14 Feb 2024 11:08:02 +0100 Subject: [PATCH 03/45] Use empty proto file to make baseline compile --- GrpcInterface/GrpcProtos/GridWebviz.proto | 89 ----------------------- 1 file changed, 89 deletions(-) diff --git a/GrpcInterface/GrpcProtos/GridWebviz.proto b/GrpcInterface/GrpcProtos/GridWebviz.proto index e95a186e94..f785b94f2e 100644 --- a/GrpcInterface/GrpcProtos/GridWebviz.proto +++ b/GrpcInterface/GrpcProtos/GridWebviz.proto @@ -3,92 +3,3 @@ syntax = "proto3"; // Will this work if we import only part of the protos? package rips; -service GridWebviz -{ - rpc getGridSurface(GetGridSurfaceRequest) returns (GetGridSurfaceResponse); - rpc cutAlongPolyline(CutAlongPolylineRequest) returns (CutAlongPolylineResponse); -} - - -message Vec2d -{ - double x = 1; - double y = 2; -} - -message Vec3d -{ - double x = 1; - double y = 2; - double z = 3; -} - -message IJKIndexFilter -{ - int32 iMin = 1; - int32 iMax = 2; - int32 jMin = 3; - int32 jMax = 4; - int32 kMin = 5; - int32 kMax = 6; -} - -message CellIndexFilter -{ - repeated fixed32 cellIndicesArr = 1; -} - -message PropertyFilter -{ - // Timestep ?? - string propertyFilename = 1; - float valueMin = 2; - float valueMax = 3; -} - -message GridDimensions -{ - uint32 iNum = 1; - uint32 jNum = 2; - uint32 kNum = 3; -} - -message GetGridSurfaceRequest -{ - string gridFilename = 1; - IJKIndexFilter ijkIndexFilter = 2; - CellIndexFilter cellIndexFilter = 3; - PropertyFilter propertyFilter = 4; -} - -message GetGridSurfaceResponse -{ - repeated float vertexArray = 1; - repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long - repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long - GridDimensions gridDimensions = 5; - Vec3d originUtm = 6; -} - -message CutAlongPolylineRequest -{ - string gridFilename = 1; - repeated double fencePolylineUtmXY = 2; -} - -message FenceMeshSection -{ - // U-axis defined by vector from start to end, Z is global Z - repeated float vertexArrayUZ = 1; - repeated fixed32 polyIndicesArr = 2; - repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long - repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long - Vec2d startUtmXY = 6; - Vec2d endUtmXY = 7; -} - -message CutAlongPolylineResponse -{ - repeated FenceMeshSection feceMeshSections = 1; - GridDimensions gridDimensions = 2; -} From a8e1c8e88ce3f338674fcfe6a4ff5d10976c41e8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Wed, 14 Feb 2024 13:29:12 +0100 Subject: [PATCH 04/45] Trigger dummy build --- GrpcInterface/GrpcProtos/GridWebviz.proto | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GrpcInterface/GrpcProtos/GridWebviz.proto b/GrpcInterface/GrpcProtos/GridWebviz.proto index f785b94f2e..7ba8f53e10 100644 --- a/GrpcInterface/GrpcProtos/GridWebviz.proto +++ b/GrpcInterface/GrpcProtos/GridWebviz.proto @@ -3,3 +3,6 @@ syntax = "proto3"; // Will this work if we import only part of the protos? package rips; + + +// test \ No newline at end of file From 9eec4e6d4bd778662b41ec1bd4246af59e427538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 19 Feb 2024 15:07:40 +0100 Subject: [PATCH 05/45] Initial testing of GetGridSurface with mocked data --- .../cvfStructGridGeometryGenerator.cpp | 15 ++ .../cvfStructGridGeometryGenerator.h | 2 + GrpcInterface/CMakeLists.txt | 20 ++- GrpcInterface/GrpcProtos/Case.proto | 1 + GrpcInterface/GrpcProtos/Definitions.proto | 14 +- GrpcInterface/GrpcProtos/Grid.proto | 1 + .../GrpcProtos/GridGeometryExtraction.proto | 76 ++++++++++ GrpcInterface/GrpcProtos/GridWebviz.proto | 8 -- GrpcInterface/GrpcProtos/NNCProperties.proto | 1 + GrpcInterface/GrpcProtos/SimulationWell.proto | 1 + GrpcInterface/GrpcProtos/VectorDefines.proto | 22 +++ .../grid_geometry_extraction_TEST.py | 65 +++++++++ GrpcInterface/Python/rips/grid.py | 6 +- .../RiaGrpcGridGeometryExtractionService.cpp | 135 ++++++++++++++++++ .../RiaGrpcGridGeometryExtractionService.h | 54 +++++++ 15 files changed, 396 insertions(+), 25 deletions(-) create mode 100644 GrpcInterface/GrpcProtos/GridGeometryExtraction.proto delete mode 100644 GrpcInterface/GrpcProtos/GridWebviz.proto create mode 100644 GrpcInterface/GrpcProtos/VectorDefines.proto create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py create mode 100644 GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp create mode 100644 GrpcInterface/RiaGrpcGridGeometryExtractionService.h diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index 6eef13a527..e3adc65f1b 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -211,6 +211,21 @@ ref StructGridGeometryGenerator::generateSurface() return geo; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref StructGridGeometryGenerator::getOrCreateVertices() +{ + if ( m_vertices.isNull() || m_vertices->size() == 0 ) + { + computeArrays(); + } + + CVF_ASSERT( m_vertices.notNull() ); + + return m_vertices; +} + //-------------------------------------------------------------------------------------------------- /// Generates simplified mesh as line drawing /// Must call generateSurface first diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index b5cb0ccc78..f8eb106d50 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -195,6 +195,8 @@ class StructGridGeometryGenerator : public Object ref createMeshDrawable(); ref createOutlineMeshDrawable( double creaseAngle ); + cvf::ref getOrCreateVertices(); + static ref createMeshDrawableFromSingleCell( const StructGridInterface* grid, size_t cellIndex ); static ref createMeshDrawableFromSingleCell( const StructGridInterface* grid, diff --git a/GrpcInterface/CMakeLists.txt b/GrpcInterface/CMakeLists.txt index 64fcfc6f6c..8cc5a5ea45 100644 --- a/GrpcInterface/CMakeLists.txt +++ b/GrpcInterface/CMakeLists.txt @@ -49,6 +49,7 @@ set(SOURCE_GROUP_HEADER_FILES RiaGrpcNNCPropertiesService.h RiaGrpcPdmObjectService.h RiaGrpcApplicationInterface.h + RiaGrpcGridGeometryExtractionService.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -64,7 +65,9 @@ set(SOURCE_GROUP_SOURCE_FILES RiaGrpcPropertiesService.cpp RiaGrpcNNCPropertiesService.cpp RiaGrpcPdmObjectService.cpp - RiaGrpcApplicationInterface.cpp) + RiaGrpcApplicationInterface.cpp + RiaGrpcGridGeometryExtractionService.cpp +) # Find Protobuf installation Looks for protobuf-config.cmake file installed by # Protobuf's cmake installation. @@ -136,7 +139,20 @@ set(_LINK_LIBRARIES ApplicationLibCode) # Proto files -file(GLOB GRPC_PROTO_FILES GrpcProtos/*.proto) +set(GRPC_PROTO_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/App.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Case.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Commands.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Definitions.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Grid.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/GridGeometryExtraction.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/NNCProperties.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/PdmObject.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Project.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/Properties.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/SimulationWell.proto + ${CMAKE_CURRENT_SOURCE_DIR}/GrpcProtos/VectorDefines.proto +) set(GRPC_PYTHON_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Python") diff --git a/GrpcInterface/GrpcProtos/Case.proto b/GrpcInterface/GrpcProtos/Case.proto index 61b3acc3bb..af99aa43a5 100644 --- a/GrpcInterface/GrpcProtos/Case.proto +++ b/GrpcInterface/GrpcProtos/Case.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "PdmObject.proto"; import "Definitions.proto"; +import "VectorDefines.proto"; package rips; diff --git a/GrpcInterface/GrpcProtos/Definitions.proto b/GrpcInterface/GrpcProtos/Definitions.proto index d6b6678d55..68e7defa97 100644 --- a/GrpcInterface/GrpcProtos/Definitions.proto +++ b/GrpcInterface/GrpcProtos/Definitions.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "VectorDefines.proto"; + package rips; message Empty @@ -11,18 +13,6 @@ message ClientToServerStreamReply int64 accepted_value_count = 1; } -message Vec3i { - int32 i = 1; - int32 j = 2; - int32 k = 3; -} - -message Vec3d -{ - double x = 1; - double y = 2; - double z = 3; -} message CellCenters { diff --git a/GrpcInterface/GrpcProtos/Grid.proto b/GrpcInterface/GrpcProtos/Grid.proto index d501747d04..cc46e4bb81 100644 --- a/GrpcInterface/GrpcProtos/Grid.proto +++ b/GrpcInterface/GrpcProtos/Grid.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package rips; import "Definitions.proto"; +import "VectorDefines.proto"; import "Case.proto"; service Grid diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto new file mode 100644 index 0000000000..569e31eddb --- /dev/null +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -0,0 +1,76 @@ +syntax = "proto3"; + +import "Grid.proto"; +import "VectorDefines.proto"; + +// Will this work if we import only part of the protos? +package rips; + +service GridGeometryExtraction +{ + rpc GetGridSurface(GetGridSurfaceRequest) returns (GetGridSurfaceResponse); + rpc CutAlongPolyline(CutAlongPolylineRequest) returns (CutAlongPolylineResponse); +} + +message IJKIndexFilter +{ + int32 iMin = 1; + int32 iMax = 2; + int32 jMin = 3; + int32 jMax = 4; + int32 kMin = 5; + int32 kMax = 6; +} + +message CellIndexFilter +{ + repeated fixed32 cellIndicesArr = 1; +} + +message PropertyFilter +{ + // Timestep ?? + string propertyFilename = 1; + float valueMin = 2; + float valueMax = 3; +} + +message GetGridSurfaceRequest +{ + string gridFilename = 1; + IJKIndexFilter ijkIndexFilter = 2; + CellIndexFilter cellIndexFilter = 3; + PropertyFilter propertyFilter = 4; +} + +message GetGridSurfaceResponse +{ + repeated float vertexArray = 1; + repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long + repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long + GridDimensions gridDimensions = 5; + Vec3d originUtm = 6; +} + +message CutAlongPolylineRequest +{ + string gridFilename = 1; + repeated double fencePolylineUtmXY = 2; +} + +message FenceMeshSection +{ + // U-axis defined by vector from start to end, Z is global Z + repeated float vertexArrayUZ = 1; + repeated fixed32 polyIndicesArr = 2; + repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long + repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long + Vec2d startUtmXY = 6; + Vec2d endUtmXY = 7; +} + +message CutAlongPolylineResponse +{ + repeated FenceMeshSection feceMeshSections = 1; + GridDimensions gridDimensions = 2; +} diff --git a/GrpcInterface/GrpcProtos/GridWebviz.proto b/GrpcInterface/GrpcProtos/GridWebviz.proto deleted file mode 100644 index 7ba8f53e10..0000000000 --- a/GrpcInterface/GrpcProtos/GridWebviz.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -// Will this work if we import only part of the protos? -package rips; - - - -// test \ No newline at end of file diff --git a/GrpcInterface/GrpcProtos/NNCProperties.proto b/GrpcInterface/GrpcProtos/NNCProperties.proto index 8fa510c220..eb7704eb87 100644 --- a/GrpcInterface/GrpcProtos/NNCProperties.proto +++ b/GrpcInterface/GrpcProtos/NNCProperties.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "Case.proto"; import "Definitions.proto"; +import "VectorDefines.proto"; package rips; diff --git a/GrpcInterface/GrpcProtos/SimulationWell.proto b/GrpcInterface/GrpcProtos/SimulationWell.proto index 65821e128a..4b1c8da4ca 100644 --- a/GrpcInterface/GrpcProtos/SimulationWell.proto +++ b/GrpcInterface/GrpcProtos/SimulationWell.proto @@ -1,6 +1,7 @@ syntax = "proto3"; import "Definitions.proto"; +import "VectorDefines.proto"; package rips; diff --git a/GrpcInterface/GrpcProtos/VectorDefines.proto b/GrpcInterface/GrpcProtos/VectorDefines.proto new file mode 100644 index 0000000000..2b46de83e0 --- /dev/null +++ b/GrpcInterface/GrpcProtos/VectorDefines.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package rips; + +message Vec3i { + int32 i = 1; + int32 j = 2; + int32 k = 3; +} + +message Vec2d +{ + double x = 1; + double y = 2; +} + +message Vec3d +{ + double x = 1; + double y = 2; + double z = 3; +} diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py new file mode 100644 index 0000000000..d02aaea524 --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py @@ -0,0 +1,65 @@ +import sys +import os + +import numpy as np + +import plotly.graph_objects as go + +sys.path.insert(1, os.path.join(sys.path[0], "../")) + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(gridFilename=None, ijkIndexFilter=None,cellIndexFilter=None,propertyFilter=None) +get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) + +get_grid_surface_response.gridDimensions +vertex_array = get_grid_surface_response.vertexArray +quad_indices_array = get_grid_surface_response.quadIndicesArr + +num_vertex_coords = 3 # [x, y, z] +num_vertices_per_quad = 4 # [v1, v2, v3, v4] +num_quads = len(vertex_array) /(num_vertex_coords * num_vertices_per_quad) + +x_array = [] +y_array = [] +z_array = [] + +# Create x-, y-, and z-arrays +for i in range(0, len(vertex_array), num_vertex_coords): + x_array.append(vertex_array[i]) + y_array.append(vertex_array[i+1]) + z_array.append(vertex_array[i+2]) + +# Create triangular mesh +i_array = [] +j_array = [] +k_array = [] +for i in range(0, len(quad_indices_array), num_vertices_per_quad): + # Set the indices of the vertices of the triangles + i_array.extend([i, i]) + j_array.extend([i+1, i+2]) + k_array.extend([i+2, i+3]) + + + +fig = go.Figure(data=[go.Mesh3d( + x=x_array, + y=y_array, + z=z_array, + i=i_array, + j=j_array, + k=k_array, + intensity = np.linspace(-5, 5, 1000, endpoint=True), + showscale=True, + colorscale=[[0, 'gold'],[0.5, 'mediumturquoise'],[1.0, 'magenta']] +)]) + +print(fig.data) + +fig.show() + diff --git a/GrpcInterface/Python/rips/grid.py b/GrpcInterface/Python/rips/grid.py index e4f669f1e8..fd3f5c56c1 100644 --- a/GrpcInterface/Python/rips/grid.py +++ b/GrpcInterface/Python/rips/grid.py @@ -8,7 +8,7 @@ import Case_pb2 import Grid_pb2 import Grid_pb2_grpc -import Definitions_pb2 +import VectorDefines_pb2 from typing import Tuple, Optional, List from grpc import Channel @@ -30,7 +30,7 @@ def __init__(self, index: int, case: Case, channel: Channel) -> None: self.index: int = index self.cached_dimensions = None - def dimensions(self) -> Optional[Definitions_pb2.Vec3i]: + def dimensions(self) -> Optional[VectorDefines_pb2.Vec3i]: """The dimensions in i, j, k direction Returns: @@ -58,7 +58,7 @@ def cell_centers_async(self): for chunk in chunks: yield chunk - def cell_centers(self) -> List[Definitions_pb2.Vec3d]: + def cell_centers(self) -> List[VectorDefines_pb2.Vec3d]: """The cell center for all cells in given grid Returns: diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp new file mode 100644 index 0000000000..a15944f49d --- /dev/null +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -0,0 +1,135 @@ +#include "RiaGrpcGridGeometryExtractionService.h" + +#include "qstring.h" + +#include "cvfStructGridGeometryGenerator.h" + +#include "RiaApplication.h" +#include "RiaGrpcCallbacks.h" +#include "RiaGrpcHelper.h" + +#include "RigEclipseCaseData.h" +#include "RigFemPartCollection.h" +#include "RigFemPartGrid.h" +#include "RigGeoMechCaseData.h" +#include "RigGridBase.h" +#include "RigMainGrid.h" +#include "RimCase.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RimGeoMechCase.h" +#include "RimGridView.h" +#include "RimProject.h" +#include "cvfArray.h" +#include "cvfDrawableGeo.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerContext* context, + const rips::GetGridSurfaceRequest* request, + rips::GetGridSurfaceResponse* response ) +{ + // Get resinsight instance and open grid + RiaApplication* applicationInstance = RiaApplication::instance(); + + if ( applicationInstance == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "ResInsight instance not found" ); + } + + applicationInstance->createMockModel(); + + RimProject* project = applicationInstance->project(); + if ( project == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No project found" ); + } + + // 1) + { + // 1. RimEclipseView + // 2. RivReservoirViewPartMgr using reservoirGridPartManager() + // 3. reservoirPartManager(RivCellSetEnum::RANGE_FILTERED, timeStepIndex); , timeStepIndex = 0 (make method + // public?) + // 4. ... ? + } + + // 2) + { + // Temporary code using mainGrid + auto eclipseCases = project->eclipseCases(); + if ( eclipseCases.empty() ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid cases found" ); + } + auto* eclipseCase = eclipseCases.front(); + auto* mainGrid = eclipseCase->eclipseCaseData()->mainGrid(); + + // Get RigFemPartGrid object ? + cvf::StructGridGeometryGenerator gridGeometryGenerator( mainGrid, false ); + + cvf::UByteArray* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() ); + cellVisibilities->setAll( 1 ); + auto* faceVisibilityFilter = new RigGridCellFaceVisibilityFilter( mainGrid ); + + gridGeometryGenerator.setCellVisibility( cellVisibilities ); + gridGeometryGenerator.addFaceVisibilityFilter( faceVisibilityFilter ); + + auto gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); + if ( gridSurfaceVertices.p() == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); + } + + // Set vertex_array and quadindicesarr response + const auto* verticesArray = gridSurfaceVertices.p(); + for ( int i = 0; i < verticesArray->size(); ++i ) + { + const auto& vertex = verticesArray->get( i ); + response->add_vertexarray( vertex.x() ); + response->add_vertexarray( vertex.y() ); + response->add_vertexarray( vertex.z() ); + + response->add_quadindicesarr( i ); + } + } + + // TODO: Add: + // - sourceCellIndicesArr + // - gridDimensions + // - originUtm + + applicationInstance->closeProject(); + + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::ServerContext* context, + const rips::CutAlongPolylineRequest* request, + rips::CutAlongPolylineResponse* response ) +{ + return grpc::Status( grpc::StatusCode::UNIMPLEMENTED, "Not implemented" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcGridGeometryExtractionService::createCallbacks() +{ + typedef RiaGrpcGridGeometryExtractionService Self; + + return { new RiaGrpcUnaryCallback( this, + &Self::GetGridSurface, + &Self::RequestGetGridSurface ), + new RiaGrpcUnaryCallback( this, + &Self::CutAlongPolyline, + &Self::RequestCutAlongPolyline ) }; +} + +static bool RiaGrpcGridGeometryExtractionService_init = + RiaGrpcServiceFactory::instance()->registerCreator( + typeid( RiaGrpcGridGeometryExtractionService ).hash_code() ); diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h new file mode 100644 index 0000000000..80ec370499 --- /dev/null +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -0,0 +1,54 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "GridGeometryExtraction.grpc.pb.h" +#include "RiaGrpcServiceInterface.h" + +#include + +namespace rips +{ +class GetGridSurfaceRequest; +class GetGridSurfaceResponse; +class CutAlongPolylineRequest; +class CutAlongPolylineResponse; +} // namespace rips + +class RiaGrpcCallbackInterface; + +//================================================================================================== +// +// gRPC-service answering requests about grid geometry extraction +// +//================================================================================================== +class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtraction::AsyncService, + public RiaGrpcServiceInterface +{ +public: + grpc::Status GetGridSurface( grpc::ServerContext* context, + const rips::GetGridSurfaceRequest* request, + rips::GetGridSurfaceResponse* response ) override; + + grpc::Status CutAlongPolyline( grpc::ServerContext* context, + const rips::CutAlongPolylineRequest* request, + rips::CutAlongPolylineResponse* response ) override; + +public: + std::vector createCallbacks() override; +}; From 9d186051d2568a11348e87854568dd13a7c0b2b4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:43:36 +0100 Subject: [PATCH 06/45] Python code linting changes detected by black (#11211) Co-authored-by: jorgenherje --- .../grid_geometry_extraction_TEST.py | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py index d02aaea524..f260f6ffd7 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py @@ -8,22 +8,26 @@ sys.path.insert(1, os.path.join(sys.path[0], "../")) from rips.instance import * -from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * from rips.generated.GridGeometryExtraction_pb2 import * rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(gridFilename=None, ijkIndexFilter=None,cellIndexFilter=None,propertyFilter=None) -get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) +get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( + gridFilename=None, ijkIndexFilter=None, cellIndexFilter=None, propertyFilter=None +) +get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = ( + grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) +) get_grid_surface_response.gridDimensions vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr -num_vertex_coords = 3 # [x, y, z] -num_vertices_per_quad = 4 # [v1, v2, v3, v4] -num_quads = len(vertex_array) /(num_vertex_coords * num_vertices_per_quad) +num_vertex_coords = 3 # [x, y, z] +num_vertices_per_quad = 4 # [v1, v2, v3, v4] +num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad) x_array = [] y_array = [] @@ -32,8 +36,8 @@ # Create x-, y-, and z-arrays for i in range(0, len(vertex_array), num_vertex_coords): x_array.append(vertex_array[i]) - y_array.append(vertex_array[i+1]) - z_array.append(vertex_array[i+2]) + y_array.append(vertex_array[i + 1]) + z_array.append(vertex_array[i + 2]) # Create triangular mesh i_array = [] @@ -42,24 +46,26 @@ for i in range(0, len(quad_indices_array), num_vertices_per_quad): # Set the indices of the vertices of the triangles i_array.extend([i, i]) - j_array.extend([i+1, i+2]) - k_array.extend([i+2, i+3]) - - - -fig = go.Figure(data=[go.Mesh3d( - x=x_array, - y=y_array, - z=z_array, - i=i_array, - j=j_array, - k=k_array, - intensity = np.linspace(-5, 5, 1000, endpoint=True), - showscale=True, - colorscale=[[0, 'gold'],[0.5, 'mediumturquoise'],[1.0, 'magenta']] -)]) + j_array.extend([i + 1, i + 2]) + k_array.extend([i + 2, i + 3]) + + +fig = go.Figure( + data=[ + go.Mesh3d( + x=x_array, + y=y_array, + z=z_array, + i=i_array, + j=j_array, + k=k_array, + intensity=np.linspace(-5, 5, 1000, endpoint=True), + showscale=True, + colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], + ) + ] +) print(fig.data) fig.show() - From 76f2607190979c01e6243cd6152b40ed1e2c5e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 22 Feb 2024 14:10:31 +0100 Subject: [PATCH 07/45] Initial GetGridSurface with IJK-filter --- .../ModelVisualization/RivGridPartMgr.cpp | 27 ++ .../ModelVisualization/RivGridPartMgr.h | 5 + .../RivReservoirPartMgr.cpp | 16 + .../ModelVisualization/RivReservoirPartMgr.h | 2 + .../RivReservoirViewPartMgr.cpp | 8 + .../RivReservoirViewPartMgr.h | 2 + .../cvfStructGridGeometryGenerator.cpp | 7 +- .../cvfStructGridGeometryGenerator.h | 4 +- .../grid_geometry_extraction_TEST.py | 12 +- .../RiaGrpcGridGeometryExtractionService.cpp | 296 ++++++++++++++---- .../RiaGrpcGridGeometryExtractionService.h | 19 ++ 11 files changed, 338 insertions(+), 60 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp index 935d35d4bc..245b3c3924 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp @@ -203,6 +203,33 @@ void RivGridPartMgr::appendPartsToModel( cvf::ModelBasicList* model ) if ( m_surfaceGridLines.notNull() ) model->addPart( m_surfaceGridLines.p() ); } +//-------------------------------------------------------------------------------------------------- +/// Returns the surface vertices of the grid part +/// +/// Creates vertices if they do not exist +/// Used for gRPC service GridGeometryExtraction +//-------------------------------------------------------------------------------------------------- +cvf::Vec3fArray* RivGridPartMgr::getOrCreateSurfaceVertices() +{ + return m_surfaceGenerator.getOrCreateVertices(); +} + +//-------------------------------------------------------------------------------------------------- +/// Get map from quad index to cell index +/// +/// Used for gRPC service GridGeometryExtraction +//-------------------------------------------------------------------------------------------------- +std::vector RivGridPartMgr::getSurfaceQuadToCellIndicesArray() +{ + auto* gridQuadToCellFaceMapper = m_surfaceGenerator.quadToCellFaceMapper(); + if ( gridQuadToCellFaceMapper == nullptr ) + { + return std::vector(); + } + + return gridQuadToCellFaceMapper->quadToCellIndicesArray(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h index f4a42d560b..4085ef520f 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h @@ -30,6 +30,8 @@ #include "cvfStructGridGeometryGenerator.h" +#include + namespace cvf { class StructGridInterface; @@ -69,6 +71,9 @@ class RivGridPartMgr : public cvf::Object void appendPartsToModel( cvf::ModelBasicList* model ); + cvf::Vec3fArray* getOrCreateSurfaceVertices(); + std::vector getSurfaceQuadToCellIndicesArray(); + private: void generatePartGeometry( cvf::StructGridGeometryGenerator& geoBuilder ); diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp index 6d7381bf2f..d833d1858e 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -179,6 +179,22 @@ void RivReservoirPartMgr::appendElementVectorResultPartsToModel( cvf::ModelBasic } } +//-------------------------------------------------------------------------------------------------- +/// Get the part manager for main grid +/// +/// Needed for the gRPC service for GridGeometryExtraction +//-------------------------------------------------------------------------------------------------- +RivGridPartMgr* RivReservoirPartMgr::mainGridPartManager() +{ + if ( m_allGrids.empty() ) + { + return nullptr; + } + + // First grid should be the main grid + return m_allGrids.at( 0 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h index 0af3afd57c..1aaf936ef0 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h @@ -76,6 +76,8 @@ class RivReservoirPartMgr : public cvf::Object // Element Vector Result void appendElementVectorResultPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ); + RivGridPartMgr* mainGridPartManager(); + private: cvf::Collection m_allGrids; // Main grid and all LGR's cvf::ref m_elementVectorResultMgr; diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp index ac55abb8f4..d498859838 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -910,6 +910,14 @@ void RivReservoirViewPartMgr::computePropertyVisibility( cvf::UByteArray* } } +//-------------------------------------------------------------------------------------------------- +/// Needed for the gRPC service for GridGeometryExtraction +//-------------------------------------------------------------------------------------------------- +RivReservoirPartMgr* RivReservoirViewPartMgr::rangeFilteredReservoirPartManager( size_t timeStepIndex ) +{ + return reservoirPartManager( RivCellSetEnum::RANGE_FILTERED, timeStepIndex ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h index d59d25b997..f8f8e25745 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -97,6 +97,8 @@ class RivReservoirViewPartMgr : public cvf::Object const cvf::UByteArray* rangeFilterVisibility, RimEclipsePropertyFilterCollection* propFilterColl ); + RivReservoirPartMgr* rangeFilteredReservoirPartManager( size_t timeStepIndex ); + private: void createGeometry( RivCellSetEnum geometryType ); void computeVisibility( cvf::UByteArray* cellVisibility, RivCellSetEnum geometryType, RigGridBase* grid, size_t gridIdx ); diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp index e3adc65f1b..d6a0893c13 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.cpp @@ -212,9 +212,12 @@ ref StructGridGeometryGenerator::generateSurface() } //-------------------------------------------------------------------------------------------------- +/// Get the vertices of the generated surface, if the vertices have not been generated yet, +/// they will be generated. /// +/// Needed for the gRPC service for GridGeometryExtraction //-------------------------------------------------------------------------------------------------- -cvf::ref StructGridGeometryGenerator::getOrCreateVertices() +Vec3fArray* StructGridGeometryGenerator::getOrCreateVertices() { if ( m_vertices.isNull() || m_vertices->size() == 0 ) { @@ -223,7 +226,7 @@ cvf::ref StructGridGeometryGenerator::getOrCreateVertices() CVF_ASSERT( m_vertices.notNull() ); - return m_vertices; + return m_vertices.p(); } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h index f8eb106d50..3b1128bfc3 100644 --- a/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h +++ b/Fwk/AppFwk/CommonCode/cvfStructGridGeometryGenerator.h @@ -137,6 +137,8 @@ class StructGridQuadToCellFaceMapper : public Object std::vector& quadToCellIndexMap() { return m_quadsToCells; } std::vector& quadToCellFaceMap() { return m_quadsToFace; } + const std::vector quadToCellIndicesArray() const { return m_quadsToCells; } + private: std::vector m_quadsToCells; std::vector m_quadsToFace; @@ -195,7 +197,7 @@ class StructGridGeometryGenerator : public Object ref createMeshDrawable(); ref createOutlineMeshDrawable( double creaseAngle ); - cvf::ref getOrCreateVertices(); + Vec3fArray* getOrCreateVertices(); static ref createMeshDrawableFromSingleCell( const StructGridInterface* grid, size_t cellIndex ); diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py index d02aaea524..39d6caf8e3 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py @@ -14,12 +14,18 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(gridFilename=None, ijkIndexFilter=None,cellIndexFilter=None,propertyFilter=None) +grid_file_name = None +ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(iMin=0, iMax =1, jMin=2, jMax=3, kMin=0, kMax=3) + +get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest(gridFilename=grid_file_name, ijkIndexFilter=ijk_index_filter,cellIndexFilter=None,propertyFilter=None) get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) get_grid_surface_response.gridDimensions vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr +origin_utm = get_grid_surface_response.originUtm +source_cell_indices_arr = get_grid_surface_response.sourceCellIndicesArr +grid_dimensions = get_grid_surface_response.gridDimensions num_vertex_coords = 3 # [x, y, z] num_vertices_per_quad = 4 # [v1, v2, v3, v4] @@ -59,6 +65,10 @@ colorscale=[[0, 'gold'],[0.5, 'mediumturquoise'],[1.0, 'magenta']] )]) +print(f"Number of quads: {num_quads}") +print(f"Source cell indices array length: {len(source_cell_indices_arr)}") +print(f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]") +print(f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]") print(fig.data) fig.show() diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index a15944f49d..c8394da9b9 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -1,13 +1,14 @@ #include "RiaGrpcGridGeometryExtractionService.h" -#include "qstring.h" +// #include "VectorDefines.pb.h" -#include "cvfStructGridGeometryGenerator.h" +#include "qstring.h" +#include "Commands/RicImportGeneralDataFeature.h" #include "RiaApplication.h" #include "RiaGrpcCallbacks.h" #include "RiaGrpcHelper.h" - +#include "RifReaderSettings.h" #include "RigEclipseCaseData.h" #include "RigFemPartCollection.h" #include "RigFemPartGrid.h" @@ -15,13 +16,25 @@ #include "RigGridBase.h" #include "RigMainGrid.h" #include "RimCase.h" +#include "RimCellFilterCollection.h" +#include "RimCellRangeFilter.h" #include "RimEclipseCase.h" #include "RimEclipseView.h" #include "RimGeoMechCase.h" #include "RimGridView.h" #include "RimProject.h" +#include "RivGridPartMgr.h" +#include "RivReservoirPartMgr.h" +#include "RivReservoirViewPartMgr.h" + +#include "cafSelectionManagerTools.h" + #include "cvfArray.h" #include "cvfDrawableGeo.h" +#include "cvfStructGridGeometryGenerator.h" + +#include "qfileinfo.h" +#include "qstring.h" //-------------------------------------------------------------------------------------------------- /// @@ -30,77 +43,84 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC const rips::GetGridSurfaceRequest* request, rips::GetGridSurfaceResponse* response ) { - // Get resinsight instance and open grid - RiaApplication* applicationInstance = RiaApplication::instance(); + // Reset all pointers + resetInternalPointers(); - if ( applicationInstance == nullptr ) + // Initialize pointer + auto firstStatus = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); + if ( firstStatus.error_code() != grpc::StatusCode::OK ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "ResInsight instance not found" ); + return firstStatus; } - applicationInstance->createMockModel(); - - RimProject* project = applicationInstance->project(); - if ( project == nullptr ) + // Apply ijk-filtering - assuming 0-indexing from gRPC + auto secondStatus = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); + if ( secondStatus.error_code() != grpc::StatusCode::OK ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No project found" ); + return secondStatus; } - // 1) + // Retrieve grid surface vertices from eclipse view + auto thirdStatus = initializeMainGridPartManagerFromEclipseView(); + if ( thirdStatus.error_code() != grpc::StatusCode::OK ) { - // 1. RimEclipseView - // 2. RivReservoirViewPartMgr using reservoirGridPartManager() - // 3. reservoirPartManager(RivCellSetEnum::RANGE_FILTERED, timeStepIndex); , timeStepIndex = 0 (make method - // public?) - // 4. ... ? + return thirdStatus; } - // 2) + auto* gridSurfaceVertices = m_mainGridPartManager->getOrCreateSurfaceVertices(); + if ( gridSurfaceVertices == nullptr ) { - // Temporary code using mainGrid - auto eclipseCases = project->eclipseCases(); - if ( eclipseCases.empty() ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid cases found" ); - } - auto* eclipseCase = eclipseCases.front(); - auto* mainGrid = eclipseCase->eclipseCaseData()->mainGrid(); - - // Get RigFemPartGrid object ? - cvf::StructGridGeometryGenerator gridGeometryGenerator( mainGrid, false ); - - cvf::UByteArray* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() ); - cellVisibilities->setAll( 1 ); - auto* faceVisibilityFilter = new RigGridCellFaceVisibilityFilter( mainGrid ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); + } - gridGeometryGenerator.setCellVisibility( cellVisibilities ); - gridGeometryGenerator.addFaceVisibilityFilter( faceVisibilityFilter ); + // Set vertex_array and quadindicesarr response + for ( int i = 0; i < gridSurfaceVertices->size(); ++i ) + { + const auto& vertex = gridSurfaceVertices->get( i ); + response->add_vertexarray( vertex.x() ); + response->add_vertexarray( vertex.y() ); + response->add_vertexarray( vertex.z() ); - auto gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); - if ( gridSurfaceVertices.p() == nullptr ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); - } + response->add_quadindicesarr( i ); + } - // Set vertex_array and quadindicesarr response - const auto* verticesArray = gridSurfaceVertices.p(); - for ( int i = 0; i < verticesArray->size(); ++i ) - { - const auto& vertex = verticesArray->get( i ); - response->add_vertexarray( vertex.x() ); - response->add_vertexarray( vertex.y() ); - response->add_vertexarray( vertex.z() ); + // Origin in utm is the offset + rips::Vec3d* modelOffset = new rips::Vec3d; + const auto mainGridModelOffset = m_eclipseView->mainGrid()->displayModelOffset(); + modelOffset->set_x( mainGridModelOffset.x() ); + modelOffset->set_y( mainGridModelOffset.y() ); + modelOffset->set_z( mainGridModelOffset.z() ); + response->set_allocated_originutm( modelOffset ); - response->add_quadindicesarr( i ); - } + // Source cell indices from main grid part manager + const auto sourceCellIndicesArray = m_mainGridPartManager->getSurfaceQuadToCellIndicesArray(); + if ( sourceCellIndicesArray.empty() ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No source cell indices array found" ); + } + for ( const auto& sourceCellIndex : sourceCellIndicesArray ) + { + response->add_sourcecellindicesarr( static_cast( sourceCellIndex ) ); } - // TODO: Add: - // - sourceCellIndicesArr - // - gridDimensions - // - originUtm + // Set grid dimensions + const auto countI = m_eclipseView->mainGrid()->cellCountI(); + const auto countJ = m_eclipseView->mainGrid()->cellCountJ(); + const auto countK = m_eclipseView->mainGrid()->cellCountK(); + rips::Vec3i* dimensions = new rips::Vec3i; + rips::GridDimensions* gridDimensions = new rips::GridDimensions; + dimensions->set_i( countI ); + dimensions->set_j( countJ ); + dimensions->set_k( countK ); + gridDimensions->set_allocated_dimensions( dimensions ); + response->set_allocated_griddimensions( gridDimensions ); - applicationInstance->closeProject(); + // Close project and return + if ( m_application != nullptr ) + { + m_application->closeProject(); + } + resetInternalPointers(); return grpc::Status::OK; } @@ -130,6 +150,170 @@ std::vector RiaGrpcGridGeometryExtractionService::cre &Self::RequestCutAlongPolyline ) }; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcGridGeometryExtractionService::resetInternalPointers() +{ + m_application = nullptr; + m_eclipseCase = nullptr; + m_eclipseView = nullptr; + m_mainGridPartManager = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// Apply ijk-filtering - assuming 0-indexing from gRPC +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ) +{ + if ( m_eclipseCase == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse case found" ); + } + if ( m_eclipseView == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse view found" ); + } + + // Find the selected Cell Filter Collection + RimCellFilterCollection* filtColl = m_eclipseView->cellFilterCollection(); + if ( filtColl == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No cell filter collection found for eclipse view" ); + } + + // Add range filter object + const int sliceDirection = -1; + const int gridIndex = 0; + RimCellRangeFilter* cellRangeFilter = filtColl->addNewCellRangeFilter( m_eclipseCase, gridIndex, sliceDirection ); + + // Apply ijk-filter values to range filter object + cellRangeFilter->startIndexI = filter.imin() + 1; // Eclipse indexing, first index is 1 + cellRangeFilter->startIndexJ = filter.jmin() + 1; // Eclipse indexing, first index is 1 + cellRangeFilter->startIndexK = filter.kmin() + 1; // Eclipse indexing, first index is 1 + cellRangeFilter->cellCountI = filter.imax() - filter.imin() + 1; + cellRangeFilter->cellCountJ = filter.jmax() - filter.jmin() + 1; + cellRangeFilter->cellCountK = filter.kmax() - filter.kmin() + 1; + + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::initializeMainGridPartManagerFromEclipseView() +{ + if ( m_eclipseView == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse view found" ); + } + + auto* viewPartManager = m_eclipseView->reservoirGridPartManager(); + if ( viewPartManager == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No view part manager found for eclipse view" ); + } + + // Ensure static geometry parts created prior to getting part manager + viewPartManager->ensureStaticGeometryPartsCreated( RivCellSetEnum::RANGE_FILTERED ); + + const size_t timeStepIndex = 0; + auto rangeFilteredPartManager = viewPartManager->rangeFilteredReservoirPartManager( timeStepIndex ); + + if ( rangeFilteredPartManager == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No range filtered part manager found for eclipse view" ); + } + + auto* mainGridPartManager = rangeFilteredPartManager->mainGridPartManager(); + if ( mainGridPartManager == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, + "No main grid part manager found for range filtered part manager" ); + } + m_mainGridPartManager = mainGridPartManager; + + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::loadGridGeometryFromAbsoluteFilePath( const std::string filePath ) +{ + QString absolutePath = QString::fromStdString( filePath ); + QFileInfo projectPathInfo( absolutePath ); + + std::shared_ptr readerSettings; + readerSettings = RifReaderSettings::createGridOnlyReaderSettings(); + + // TODO: Set true or false? + bool createPlot = true; + bool createView = true; + auto fileOpenMetaData = RicImportGeneralDataFeature::openEclipseFilesFromFileNames( QStringList{ absolutePath }, + createPlot, + createView, + readerSettings ); + + if ( fileOpenMetaData.createdCaseIds.empty() ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, + QString( "loadCase: Unable to load case from %1" ).arg( absolutePath ).toStdString() ); + } + return grpc::Status::OK; +} + +//-------------------------------------------------------------------------------------------------- +/// Helper function to get application instance and load eclipse case from given file path +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( + const std::string filePath ) +{ + // Get ResInsight instance and open grid + m_application = RiaApplication::instance(); + + if ( m_application == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "ResInsight instance not found" ); + } + + // Ensure existing project is closed + m_application->closeProject(); + + if ( filePath.empty() ) + { + // For empty grid file name, use mock model + m_application->createMockModel(); + } + else + { + // Load case from file name + auto status = loadGridGeometryFromAbsoluteFilePath( filePath ); + if ( status.error_code() != grpc::StatusCode::OK ) return status; + } + + RimProject* project = m_application->project(); + if ( project == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No project found" ); + } + + auto eclipseCases = project->eclipseCases(); + if ( eclipseCases.empty() || eclipseCases.front() == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse case found for project" ); + } + m_eclipseCase = eclipseCases.front(); + + if ( m_eclipseCase->views().empty() || m_eclipseCase->views().front() == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found for eclipse case" ); + } + m_eclipseView = dynamic_cast( m_eclipseCase->views().front() ); + + return grpc::Status::OK; +} + static bool RiaGrpcGridGeometryExtractionService_init = RiaGrpcServiceFactory::instance()->registerCreator( typeid( RiaGrpcGridGeometryExtractionService ).hash_code() ); diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 80ec370499..a94acaab25 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -18,7 +18,13 @@ #pragma once #include "GridGeometryExtraction.grpc.pb.h" +#include "RiaApplication.h" #include "RiaGrpcServiceInterface.h" +#include "RimEclipseCase.h" +#include "RimEclipseView.h" +#include "RivGridPartMgr.h" + +#include "cvfArray.h" #include @@ -51,4 +57,17 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr public: std::vector createCallbacks() override; + +private: + void resetInternalPointers(); + + grpc::Status loadGridGeometryFromAbsoluteFilePath( const std::string filePath ); + grpc::Status initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( const std::string filePath ); + grpc::Status initializeMainGridPartManagerFromEclipseView(); + grpc::Status applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ); + + RiaApplication* m_application = nullptr; + RimEclipseCase* m_eclipseCase = nullptr; + RimEclipseView* m_eclipseView = nullptr; + RivGridPartMgr* m_mainGridPartManager = nullptr; }; From c966938193fe8cd951cea1c3bc75b162a0c5618c Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Thu, 22 Feb 2024 13:15:09 +0000 Subject: [PATCH 08/45] Python code linting changes detected by black --- .../grid_geometry_extraction_TEST.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py index 44d4997987..5d5a5ed8c3 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py @@ -15,10 +15,15 @@ grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) grid_file_name = None -ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(iMin=0, iMax =1, jMin=2, jMax=3, kMin=0, kMax=3) +ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( + iMin=0, iMax=1, jMin=2, jMax=3, kMin=0, kMax=3 +) get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( - gridFilename=grid_file_name, ijkIndexFilter=ijk_index_filter, cellIndexFilter=None, propertyFilter=None + gridFilename=grid_file_name, + ijkIndexFilter=ijk_index_filter, + cellIndexFilter=None, + propertyFilter=None, ) get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = ( grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) @@ -74,8 +79,12 @@ print(f"Number of quads: {num_quads}") print(f"Source cell indices array length: {len(source_cell_indices_arr)}") -print(f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]") -print(f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]") +print( + f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" +) +print( + f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" +) print(fig.data) fig.show() From cebc3676e99d83f646a5207c1b02217533d12cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 22 Feb 2024 15:38:02 +0100 Subject: [PATCH 09/45] Minor adjustments --- .../grid_geometry_extraction_TEST.py | 2 +- .../RiaGrpcGridGeometryExtractionService.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py index 44d4997987..148a49993f 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py @@ -15,7 +15,7 @@ grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) grid_file_name = None -ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(iMin=0, iMax =1, jMin=2, jMax=3, kMin=0, kMax=3) +ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter(iMin=0, iMax =1, jMin=1, jMax=3, kMin=0, kMax=3) get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( gridFilename=grid_file_name, ijkIndexFilter=ijk_index_filter, cellIndexFilter=None, propertyFilter=None diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index c8394da9b9..035731abcb 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -47,24 +47,24 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC resetInternalPointers(); // Initialize pointer - auto firstStatus = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); - if ( firstStatus.error_code() != grpc::StatusCode::OK ) + grpc::Status status = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); + if ( status.error_code() != grpc::StatusCode::OK ) { - return firstStatus; + return status; } // Apply ijk-filtering - assuming 0-indexing from gRPC - auto secondStatus = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); - if ( secondStatus.error_code() != grpc::StatusCode::OK ) + status = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); + if ( status.error_code() != grpc::StatusCode::OK ) { - return secondStatus; + return status; } // Retrieve grid surface vertices from eclipse view - auto thirdStatus = initializeMainGridPartManagerFromEclipseView(); - if ( thirdStatus.error_code() != grpc::StatusCode::OK ) + status = initializeMainGridPartManagerFromEclipseView(); + if ( status.error_code() != grpc::StatusCode::OK ) { - return thirdStatus; + return status; } auto* gridSurfaceVertices = m_mainGridPartManager->getOrCreateSurfaceVertices(); From a4323c9e55a44579dfa04268dfe4613fd2c0f598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 26 Feb 2024 08:49:21 +0100 Subject: [PATCH 10/45] Rename python file --- ...ometry_extraction_TEST.py => grid_geometry_extraction.py} | 5 ----- 1 file changed, 5 deletions(-) rename GrpcInterface/Python/rips/WebvizPythonExamples/{grid_geometry_extraction_TEST.py => grid_geometry_extraction.py} (97%) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py similarity index 97% rename from GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py rename to GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py index 0981c6a670..b006ef3d6f 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_TEST.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py @@ -1,12 +1,7 @@ -import sys -import os - import numpy as np import plotly.graph_objects as go -sys.path.insert(1, os.path.join(sys.path[0], "../")) - from rips.instance import * from rips.generated.GridGeometryExtraction_pb2_grpc import * from rips.generated.GridGeometryExtraction_pb2 import * From 42a939b107f8ac8e91d95dc74716898c6124ce6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 26 Feb 2024 10:27:55 +0100 Subject: [PATCH 11/45] Check for existing ijk-filter before apply --- GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 035731abcb..8c232ebdd2 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -54,10 +54,13 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } // Apply ijk-filtering - assuming 0-indexing from gRPC - status = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); - if ( status.error_code() != grpc::StatusCode::OK ) + if ( request->has_ijkindexfilter() ) { - return status; + status = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); + if ( status.error_code() != grpc::StatusCode::OK ) + { + return status; + } } // Retrieve grid surface vertices from eclipse view From f9f4bc1e86869e7b9cf4f1b7ce789de986e78cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 26 Feb 2024 16:00:23 +0100 Subject: [PATCH 12/45] Refactor code Make use of calculateCurrentTotalCellVisibility for eclipse view to get surface vertices. Prevent usage of individual grid part managers in gRPC-service. --- .../ModelVisualization/RivGridPartMgr.cpp | 27 -- .../ModelVisualization/RivGridPartMgr.h | 3 - .../RivReservoirPartMgr.cpp | 16 -- .../ModelVisualization/RivReservoirPartMgr.h | 2 - .../RivReservoirViewPartMgr.cpp | 8 - .../RivReservoirViewPartMgr.h | 2 - .../ProjectDataModel/RimEclipseView.cpp | 239 +++++++++++------- .../ProjectDataModel/RimEclipseView.h | 7 + .../RiaGrpcGridGeometryExtractionService.cpp | 58 +++-- .../RiaGrpcGridGeometryExtractionService.h | 13 +- 10 files changed, 185 insertions(+), 190 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp index 245b3c3924..935d35d4bc 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp @@ -203,33 +203,6 @@ void RivGridPartMgr::appendPartsToModel( cvf::ModelBasicList* model ) if ( m_surfaceGridLines.notNull() ) model->addPart( m_surfaceGridLines.p() ); } -//-------------------------------------------------------------------------------------------------- -/// Returns the surface vertices of the grid part -/// -/// Creates vertices if they do not exist -/// Used for gRPC service GridGeometryExtraction -//-------------------------------------------------------------------------------------------------- -cvf::Vec3fArray* RivGridPartMgr::getOrCreateSurfaceVertices() -{ - return m_surfaceGenerator.getOrCreateVertices(); -} - -//-------------------------------------------------------------------------------------------------- -/// Get map from quad index to cell index -/// -/// Used for gRPC service GridGeometryExtraction -//-------------------------------------------------------------------------------------------------- -std::vector RivGridPartMgr::getSurfaceQuadToCellIndicesArray() -{ - auto* gridQuadToCellFaceMapper = m_surfaceGenerator.quadToCellFaceMapper(); - if ( gridQuadToCellFaceMapper == nullptr ) - { - return std::vector(); - } - - return gridQuadToCellFaceMapper->quadToCellIndicesArray(); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h index 4085ef520f..c1338f131e 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.h @@ -71,9 +71,6 @@ class RivGridPartMgr : public cvf::Object void appendPartsToModel( cvf::ModelBasicList* model ); - cvf::Vec3fArray* getOrCreateSurfaceVertices(); - std::vector getSurfaceQuadToCellIndicesArray(); - private: void generatePartGeometry( cvf::StructGridGeometryGenerator& geoBuilder ); diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp index d833d1858e..6d7381bf2f 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.cpp @@ -179,22 +179,6 @@ void RivReservoirPartMgr::appendElementVectorResultPartsToModel( cvf::ModelBasic } } -//-------------------------------------------------------------------------------------------------- -/// Get the part manager for main grid -/// -/// Needed for the gRPC service for GridGeometryExtraction -//-------------------------------------------------------------------------------------------------- -RivGridPartMgr* RivReservoirPartMgr::mainGridPartManager() -{ - if ( m_allGrids.empty() ) - { - return nullptr; - } - - // First grid should be the main grid - return m_allGrids.at( 0 ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h index 1aaf936ef0..0af3afd57c 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivReservoirPartMgr.h @@ -76,8 +76,6 @@ class RivReservoirPartMgr : public cvf::Object // Element Vector Result void appendElementVectorResultPartsToModel( cvf::ModelBasicList* model, size_t timeStepIndex ); - RivGridPartMgr* mainGridPartManager(); - private: cvf::Collection m_allGrids; // Main grid and all LGR's cvf::ref m_elementVectorResultMgr; diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp index d498859838..ac55abb8f4 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.cpp @@ -910,14 +910,6 @@ void RivReservoirViewPartMgr::computePropertyVisibility( cvf::UByteArray* } } -//-------------------------------------------------------------------------------------------------- -/// Needed for the gRPC service for GridGeometryExtraction -//-------------------------------------------------------------------------------------------------- -RivReservoirPartMgr* RivReservoirViewPartMgr::rangeFilteredReservoirPartManager( size_t timeStepIndex ) -{ - return reservoirPartManager( RivCellSetEnum::RANGE_FILTERED, timeStepIndex ); -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h index f8f8e25745..d59d25b997 100644 --- a/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h +++ b/ApplicationLibCode/ModelVisualization/RivReservoirViewPartMgr.h @@ -97,8 +97,6 @@ class RivReservoirViewPartMgr : public cvf::Object const cvf::UByteArray* rangeFilterVisibility, RimEclipsePropertyFilterCollection* propFilterColl ); - RivReservoirPartMgr* rangeFilteredReservoirPartManager( size_t timeStepIndex ); - private: void createGeometry( RivCellSetEnum geometryType ); void computeVisibility( cvf::UByteArray* cellVisibility, RivCellSetEnum geometryType, RigGridBase* grid, size_t gridIdx ); diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 00483713dd..a851c24600 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -386,96 +386,9 @@ void RimEclipseView::propagateEclipseCaseToChildObjects() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimEclipseView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +cvf::Collection RimEclipseView::frameModelsForTimeSteps() { - RimGridView::fieldChangedByUi( changedField, oldValue, newValue ); - - if ( changedField == &m_customEclipseCase ) - { - propagateEclipseCaseToChildObjects(); - - // Sync with RimReloadCaseTools::updateAll3dViews - loadDataAndUpdate(); - updateGridBoxData(); - updateAnnotationItems(); - - zoomAll(); - - return; - } - - if ( changedField == &m_showInvalidCells ) - { - scheduleGeometryRegen( INACTIVE ); - scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); - - scheduleCreateDisplayModelAndRedraw(); - } - else if ( changedField == &m_showInactiveCells ) - { - updateGridBoxData(); - - scheduleGeometryRegen( INACTIVE ); - scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); - - scheduleCreateDisplayModelAndRedraw(); - } - else if ( changedField == &m_cellFilterCollection ) - { - scheduleGeometryRegen( RANGE_FILTERED ); - scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); - - scheduleCreateDisplayModelAndRedraw(); - } - else if ( changedField == &m_propertyFilterCollection ) - { - scheduleGeometryRegen( PROPERTY_FILTERED ); - - scheduleCreateDisplayModelAndRedraw(); - } - else if ( changedField == &m_cellResultData ) - { - currentGridCellResults()->recalculateStatistics( m_cellResult->eclipseResultAddress() ); - setCurrentTimeStepAndUpdate( currentTimeStep() ); - createDisplayModelAndRedraw(); - } -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimEclipseView::onUpdateScaleTransform() -{ - cvf::Mat4d scale = cvf::Mat4d::IDENTITY; - scale( 2, 2 ) = scaleZ(); - - scaleTransform()->setLocalTransform( scale ); - m_simWellsPartManager->setScaleTransform( scaleTransform() ); - - if ( nativeOrOverrideViewer() ) nativeOrOverrideViewer()->updateCachedValuesInScene(); -} - -//-------------------------------------------------------------------------------------------------- -/// Create display model, -/// or at least empty scenes as frames that is delivered to the viewer -/// The real geometry generation is done inside RivReservoirViewGeometry and friends -//-------------------------------------------------------------------------------------------------- -void RimEclipseView::onCreateDisplayModel() -{ - clearReservoirCellVisibilities(); - - if ( nativeOrOverrideViewer() == nullptr ) return; - -#if 0 // Debug info - static int callCount = 0; - std::cout << "RimEclipseView::onCreateDisplayModel() " << callCount++ << std::endl; - RiuMainWindow::instance()->setResultInfo(QString("RimEclipseView::onCreateDisplayModel() ") + QString::number(callCount++)); -#endif - - if ( !( eclipseCase() && eclipseCase()->eclipseCaseData() ) ) return; - - const bool cellFiltersActive = cellFilterCollection()->hasActiveFilters(); - const bool propertyFiltersActive = eclipsePropertyFilterCollection()->hasActiveFilters(); + const bool hasPropertyFiltersActive = eclipsePropertyFilterCollection()->hasActiveFilters(); // Define a vector containing time step indices to produce geometry for. // First entry in this vector is used to define the geometry only result mode with no results. @@ -496,7 +409,7 @@ void RimEclipseView::onCreateDisplayModel() timeStepIndices.push_back( i ); } } - else if ( cellResult()->hasStaticResult() || cellEdgeResult()->hasResult() || propertyFiltersActive || + else if ( cellResult()->hasStaticResult() || cellEdgeResult()->hasResult() || hasPropertyFiltersActive || intersectionCollection()->hasAnyActiveSeparateResults() || ( surfaceInViewCollection() && surfaceInViewCollection()->hasAnyActiveSeparateResults() ) ) { @@ -511,11 +424,16 @@ void RimEclipseView::onCreateDisplayModel() frameModels.push_back( new cvf::ModelBasicList ); } - // Remove all existing animation frames from the viewer. - // The parts are still cached in the RivReservoir geometry and friends - nativeOrOverrideViewer()->removeAllFrames( isUsingOverrideViewer() ); + return frameModels; +} - wellCollection()->scheduleIsWellPipesVisibleRecalculation(); +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::createRequiredReservoirPartManagers( cvf::Collection frameModels ) +{ + const bool hasCellFiltersActive = cellFilterCollection()->hasActiveFilters(); + const bool hasPropertyFiltersActive = eclipsePropertyFilterCollection()->hasActiveFilters(); // Create vector of grid indices to render std::vector gridIndices = indicesToVisibleGrids(); @@ -526,7 +444,7 @@ void RimEclipseView::onCreateDisplayModel() // For property filtered geometry : just set all the models as empty scenes // updateCurrentTimeStep requests the actual parts - if ( !propertyFiltersActive || ( viewController() && viewController()->isVisibleCellsOveridden() ) ) + if ( !hasPropertyFiltersActive || ( viewController() && viewController()->isVisibleCellsOveridden() ) ) { std::vector geometryTypesToAdd; @@ -534,7 +452,7 @@ void RimEclipseView::onCreateDisplayModel() { geometryTypesToAdd.push_back( OVERRIDDEN_CELL_VISIBILITY ); } - else if ( cellFiltersActive && wellCollection()->hasVisibleWellCells() ) + else if ( hasCellFiltersActive && wellCollection()->hasVisibleWellCells() ) { geometryTypesToAdd.push_back( RANGE_FILTERED ); geometryTypesToAdd.push_back( RANGE_FILTERED_WELL_CELLS ); @@ -545,12 +463,12 @@ void RimEclipseView::onCreateDisplayModel() geometryTypesToAdd.push_back( RANGE_FILTERED_INACTIVE ); } } - else if ( !cellFiltersActive && wellCollection()->hasVisibleWellCells() ) + else if ( !hasCellFiltersActive && wellCollection()->hasVisibleWellCells() ) { geometryTypesToAdd.push_back( VISIBLE_WELL_CELLS ); geometryTypesToAdd.push_back( VISIBLE_WELL_FENCE_CELLS ); } - else if ( cellFiltersActive && !wellCollection()->hasVisibleWellCells() ) + else if ( hasCellFiltersActive && !wellCollection()->hasVisibleWellCells() ) { geometryTypesToAdd.push_back( RANGE_FILTERED ); geometryTypesToAdd.push_back( RANGE_FILTERED_WELL_CELLS ); @@ -599,6 +517,112 @@ void RimEclipseView::onCreateDisplayModel() std::vector empty; setVisibleGridParts( empty ); } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + RimGridView::fieldChangedByUi( changedField, oldValue, newValue ); + + if ( changedField == &m_customEclipseCase ) + { + propagateEclipseCaseToChildObjects(); + + // Sync with RimReloadCaseTools::updateAll3dViews + loadDataAndUpdate(); + updateGridBoxData(); + updateAnnotationItems(); + + zoomAll(); + + return; + } + + if ( changedField == &m_showInvalidCells ) + { + scheduleGeometryRegen( INACTIVE ); + scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); + + scheduleCreateDisplayModelAndRedraw(); + } + else if ( changedField == &m_showInactiveCells ) + { + updateGridBoxData(); + + scheduleGeometryRegen( INACTIVE ); + scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); + + scheduleCreateDisplayModelAndRedraw(); + } + else if ( changedField == &m_cellFilterCollection ) + { + scheduleGeometryRegen( RANGE_FILTERED ); + scheduleGeometryRegen( RANGE_FILTERED_INACTIVE ); + + scheduleCreateDisplayModelAndRedraw(); + } + else if ( changedField == &m_propertyFilterCollection ) + { + scheduleGeometryRegen( PROPERTY_FILTERED ); + + scheduleCreateDisplayModelAndRedraw(); + } + else if ( changedField == &m_cellResultData ) + { + currentGridCellResults()->recalculateStatistics( m_cellResult->eclipseResultAddress() ); + setCurrentTimeStepAndUpdate( currentTimeStep() ); + createDisplayModelAndRedraw(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::onUpdateScaleTransform() +{ + cvf::Mat4d scale = cvf::Mat4d::IDENTITY; + scale( 2, 2 ) = scaleZ(); + + scaleTransform()->setLocalTransform( scale ); + m_simWellsPartManager->setScaleTransform( scaleTransform() ); + + if ( nativeOrOverrideViewer() ) nativeOrOverrideViewer()->updateCachedValuesInScene(); +} + +//-------------------------------------------------------------------------------------------------- +/// Create display model, +/// or at least empty scenes as frames that is delivered to the viewer +/// The real geometry generation is done inside RivReservoirViewGeometry and friends +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::onCreateDisplayModel() +{ + clearReservoirCellVisibilities(); + + if ( nativeOrOverrideViewer() == nullptr ) return; + +#if 0 // Debug info + static int callCount = 0; + std::cout << "RimEclipseView::onCreateDisplayModel() " << callCount++ << std::endl; + RiuMainWindow::instance()->setResultInfo(QString("RimEclipseView::onCreateDisplayModel() ") + QString::number(callCount++)); +#endif + + if ( !( eclipseCase() && eclipseCase()->eclipseCaseData() ) ) return; + + const bool cellFiltersActive = cellFilterCollection()->hasActiveFilters(); + const bool propertyFiltersActive = eclipsePropertyFilterCollection()->hasActiveFilters(); + + // Get frame models for all time steps + cvf::Collection frameModels = frameModelsForTimeSteps(); + + // Remove all existing animation frames from the viewer. + // The parts are still cached in the RivReservoir geometry and friends + nativeOrOverrideViewer()->removeAllFrames( isUsingOverrideViewer() ); + wellCollection()->scheduleIsWellPipesVisibleRecalculation(); + + // Create required reservoir part managers + createRequiredReservoirPartManagers( frameModels ); m_reservoirGridPartManager->clearWatertightGeometryFlags(); @@ -1652,6 +1676,17 @@ std::vector RimEclipseView::additionalResultsForResultI return m_additionalResultsForResultInfo()->additionalResultAddresses(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::createGridGeometryParts() +{ + if ( !( eclipseCase() && eclipseCase()->eclipseCaseData() ) ) return; + + const auto frameModels = frameModelsForTimeSteps(); + createRequiredReservoirPartManagers( frameModels ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -2395,6 +2430,14 @@ bool RimEclipseView::showInactiveCells() const return m_showInactiveCells; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEclipseView::setShowInactiveCells( bool showInactive ) +{ + m_showInactiveCells = showInactive; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h index 75c45ee640..3a4452b371 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.h @@ -106,6 +106,8 @@ class RimEclipseView : public RimGridView bool showInvalidCells() const; bool showInactiveCells() const; + void setShowInactiveCells( bool showInactive ); + // Access internal objects const RimPropertyFilterCollection* propertyFilterCollection() const override; @@ -164,6 +166,8 @@ class RimEclipseView : public RimGridView std::vector additionalResultsForResultInfo() const; + void createGridGeometryParts(); + protected: void initAfterRead() override; void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; @@ -221,6 +225,9 @@ class RimEclipseView : public RimGridView void propagateEclipseCaseToChildObjects(); + cvf::Collection frameModelsForTimeSteps(); + void createRequiredReservoirPartManagers( cvf::Collection frameModels ); + protected: cvf::ref m_faultReactVizModel; diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 8c232ebdd2..fd94e3ff75 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -63,14 +63,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } } - // Retrieve grid surface vertices from eclipse view - status = initializeMainGridPartManagerFromEclipseView(); + // Ensure static geometry parts created for grid part manager in view + m_eclipseView->createGridGeometryParts(); + + // Initialize grid geometry generator + const bool useOpenMP = false; + auto* gridGeometryGenerator = new cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); + status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } - auto* gridSurfaceVertices = m_mainGridPartManager->getOrCreateSurfaceVertices(); + auto* gridSurfaceVertices = gridGeometryGenerator->getOrCreateVertices(); if ( gridSurfaceVertices == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); @@ -96,7 +101,11 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC response->set_allocated_originutm( modelOffset ); // Source cell indices from main grid part manager - const auto sourceCellIndicesArray = m_mainGridPartManager->getSurfaceQuadToCellIndicesArray(); + std::vector sourceCellIndicesArray = std::vector(); + if ( gridGeometryGenerator->quadToCellFaceMapper() != nullptr ) + { + sourceCellIndicesArray = gridGeometryGenerator->quadToCellFaceMapper()->quadToCellIndicesArray(); + } if ( sourceCellIndicesArray.empty() ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No source cell indices array found" ); @@ -158,10 +167,9 @@ std::vector RiaGrpcGridGeometryExtractionService::cre //-------------------------------------------------------------------------------------------------- void RiaGrpcGridGeometryExtractionService::resetInternalPointers() { - m_application = nullptr; - m_eclipseCase = nullptr; - m_eclipseView = nullptr; - m_mainGridPartManager = nullptr; + m_application = nullptr; + m_eclipseCase = nullptr; + m_eclipseView = nullptr; } //-------------------------------------------------------------------------------------------------- @@ -204,37 +212,30 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseCa //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridGeometryExtractionService::initializeMainGridPartManagerFromEclipseView() +grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGeneratorWithEclipseViewCellVisibility( + cvf::StructGridGeometryGenerator* generator ) { if ( m_eclipseView == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse view found" ); } - auto* viewPartManager = m_eclipseView->reservoirGridPartManager(); - if ( viewPartManager == nullptr ) + auto* mainGrid = m_eclipseCase->mainGrid(); + if ( mainGrid == nullptr ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No view part manager found for eclipse view" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No main grid found for eclipse view" ); } - // Ensure static geometry parts created prior to getting part manager - viewPartManager->ensureStaticGeometryPartsCreated( RivCellSetEnum::RANGE_FILTERED ); + // Cell visibilities + const int firstTimeStep = 0; + auto* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() ); + m_eclipseView->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); - const size_t timeStepIndex = 0; - auto rangeFilteredPartManager = viewPartManager->rangeFilteredReservoirPartManager( timeStepIndex ); + // Face visibility filter + auto* faceVisibilityFilter = new RigGridCellFaceVisibilityFilter( mainGrid ); - if ( rangeFilteredPartManager == nullptr ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No range filtered part manager found for eclipse view" ); - } - - auto* mainGridPartManager = rangeFilteredPartManager->mainGridPartManager(); - if ( mainGridPartManager == nullptr ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, - "No main grid part manager found for range filtered part manager" ); - } - m_mainGridPartManager = mainGridPartManager; + generator->setCellVisibility( cellVisibilities ); + generator->addFaceVisibilityFilter( faceVisibilityFilter ); return grpc::Status::OK; } @@ -313,6 +314,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeApplicationAndEclip return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found for eclipse case" ); } m_eclipseView = dynamic_cast( m_eclipseCase->views().front() ); + m_eclipseView->setShowInactiveCells( true ); return grpc::Status::OK; } diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index a94acaab25..12254b1251 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -25,6 +25,7 @@ #include "RivGridPartMgr.h" #include "cvfArray.h" +#include "cvfStructGridGeometryGenerator.h" #include @@ -62,12 +63,12 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr void resetInternalPointers(); grpc::Status loadGridGeometryFromAbsoluteFilePath( const std::string filePath ); - grpc::Status initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( const std::string filePath ); - grpc::Status initializeMainGridPartManagerFromEclipseView(); grpc::Status applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ); + grpc::Status initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( const std::string filePath ); + + grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator* generator ); - RiaApplication* m_application = nullptr; - RimEclipseCase* m_eclipseCase = nullptr; - RimEclipseView* m_eclipseView = nullptr; - RivGridPartMgr* m_mainGridPartManager = nullptr; + RiaApplication* m_application = nullptr; + RimEclipseCase* m_eclipseCase = nullptr; + RimEclipseView* m_eclipseView = nullptr; }; From 8d7986b84d95687f84edb3074cb61c78b94c7f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Tue, 27 Feb 2024 09:02:21 +0100 Subject: [PATCH 13/45] Adjust python script to add utm coords --- .../grid_geometry_extraction.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py index b006ef3d6f..e13134a4ae 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py @@ -10,9 +10,11 @@ grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) grid_file_name = None +grid_file_name = "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( iMin=0, iMax=1, jMin=1, jMax=3, kMin=0, kMax=3 ) +# ijk_index_filter = None get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( gridFilename=grid_file_name, @@ -35,15 +37,14 @@ num_vertices_per_quad = 4 # [v1, v2, v3, v4] num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad) +# Create x-, y-, and z-arrays x_array = [] y_array = [] z_array = [] - -# Create x-, y-, and z-arrays for i in range(0, len(vertex_array), num_vertex_coords): - x_array.append(vertex_array[i]) - y_array.append(vertex_array[i + 1]) - z_array.append(vertex_array[i + 2]) + x_array.append(vertex_array[i + 0] + origin_utm.x) + y_array.append(vertex_array[i + 1] + origin_utm.y) + z_array.append(vertex_array[i + 2] + origin_utm.z) # Create triangular mesh i_array = [] @@ -51,7 +52,7 @@ k_array = [] for i in range(0, len(quad_indices_array), num_vertices_per_quad): # Set the indices of the vertices of the triangles - i_array.extend([i, i]) + i_array.extend([i + 0, i + 0]) j_array.extend([i + 1, i + 2]) k_array.extend([i + 2, i + 3]) From b74c0c52edcfaa5b50834510c63e79b9d2128b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Tue, 27 Feb 2024 12:53:12 +0100 Subject: [PATCH 14/45] Replace whitespace with "_" for release names --- .github/workflows/ResInsightWithCache.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ResInsightWithCache.yml b/.github/workflows/ResInsightWithCache.yml index 7c83bd0a88..a732314c84 100644 --- a/.github/workflows/ResInsightWithCache.yml +++ b/.github/workflows/ResInsightWithCache.yml @@ -25,7 +25,7 @@ jobs: matrix: config: - { - name: "Windows Latest MSVC", + name: "Windows_Latest_MSVC", os: windows-2022, cc: "cl", cxx: "cl", @@ -38,7 +38,7 @@ jobs: publish-to-pypi: false, } - { - name: "Ubuntu 20.04 gcc", + name: "Ubuntu_20.04_gcc", os: ubuntu-20.04, cc: "gcc", cxx: "g++", @@ -51,7 +51,7 @@ jobs: publish-to-pypi: true, } - { - name: "Ubuntu 22.04 clang-16", + name: "Ubuntu_22.04_clang-16", os: ubuntu-22.04, cc: "clang-16", cxx: "clang++-16", From 53af53024cf2b42c5bf4f85907936ff52ccee706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Tue, 27 Feb 2024 12:59:22 +0100 Subject: [PATCH 15/45] Adjust python example --- .../Python/rips/WebvizPythonExamples/grid_geometry_extraction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py index e13134a4ae..996fba8178 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py @@ -10,7 +10,6 @@ grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) grid_file_name = None -grid_file_name = "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( iMin=0, iMax=1, jMin=1, jMax=3, kMin=0, kMax=3 ) From 091bd8163a94642c6132ed8d04d002b91bc1c081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 28 Feb 2024 16:10:36 +0100 Subject: [PATCH 16/45] Initial testing of CutAlongPloyline - WIP --- .../Intersections/CMakeLists_files.cmake | 2 + .../RivEclipseIntersectionGrid.cpp | 7 +- ...vPolylineIntersectionGeometryGenerator.cpp | 247 ++++++++++++++++++ ...RivPolylineIntersectionGeometryGenerator.h | 78 ++++++ .../ProjectDataModel/RimEclipseView.cpp | 2 + .../GrpcProtos/GridGeometryExtraction.proto | 8 +- .../grid_geometry_extraction_intersection.py | 82 ++++++ .../RiaGrpcGridGeometryExtractionService.cpp | 102 +++++++- 8 files changed, 522 insertions(+), 6 deletions(-) create mode 100644 ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp create mode 100644 ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py diff --git a/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake b/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake index b5c295808d..11e8c43463 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake +++ b/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake @@ -11,6 +11,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RivEclipseIntersectionGrid.h ${CMAKE_CURRENT_LIST_DIR}/RivFemIntersectionGrid.h ${CMAKE_CURRENT_LIST_DIR}/RivIntersectionGeometryGeneratorInterface.h + ${CMAKE_CURRENT_LIST_DIR}/RivPolylineIntersectionGeometryGenerator.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -24,6 +25,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RivSectionFlattener.cpp ${CMAKE_CURRENT_LIST_DIR}/RivEclipseIntersectionGrid.cpp ${CMAKE_CURRENT_LIST_DIR}/RivFemIntersectionGrid.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivPolylineIntersectionGeometryGenerator.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEclipseIntersectionGrid.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEclipseIntersectionGrid.cpp index 04c9d8ebed..f8dd09e782 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEclipseIntersectionGrid.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEclipseIntersectionGrid.cpp @@ -68,9 +68,14 @@ bool RivEclipseIntersectionGrid::useCell( size_t cellIndex ) const { const RigCell& cell = m_mainGrid->globalCellArray()[cellIndex]; if ( m_showInactiveCells ) + { return !cell.isInvalid() && ( cell.subGrid() == nullptr ); - else + } + if ( m_activeCellInfo.p() != nullptr ) + { return m_activeCellInfo->isActive( cellIndex ) && ( cell.subGrid() == nullptr ); + } + return true; } return false; } diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp new file mode 100644 index 0000000000..4d47ee1115 --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -0,0 +1,247 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// + +#include "RivPolylineIntersectionGeometryGenerator.h" + +#include "RivIntersectionHexGridInterface.h" +#include "RivSectionFlattener.h" + +#include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h" + +#include "cvfPlane.h" + +#pragma optimize( "", off ) + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerator( std::vector& polyline, + RivIntersectionHexGridInterface* grid ) + : m_polyline( polyline ) + , m_hexGrid( grid ) +{ + m_triangleVxes = new cvf::Vec3fArray; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RivPolylineIntersectionGeometryGenerator::~RivPolylineIntersectionGeometryGenerator() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const +{ + return m_triangleVxes->size() > 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RivPolylineIntersectionGeometryGenerator::triangleToCellIndex() const +{ + CVF_ASSERT( m_triangleVxes->size() > 0 ); + return m_triangleToCellIdxMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::triangleVxes() const +{ + CVF_ASSERT( m_triangleVxes->size() > 0 ); + return m_triangleVxes.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RivPolylineIntersectionGeometryGenerator::triangleVxToCellCornerInterpolationWeights() const +{ + CVF_ASSERT( m_triangleVxes->size() > 0 ); + + // Not implemented error + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf::UByteArray* visibleCells ) +{ + calculateArrays( visibleCells ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) +{ + if ( m_triangleVxes->size() != 0 || m_hexGrid.isNull() ) return; + + std::vector calculatedTriangleVertices; + + // MeshLinesAccumulator meshAcc( m_hexGrid.p() ); + + cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); + + const double topDepth = gridBBox.max().z(); + const double bottomDepth = gridBBox.min().z(); + + std::array corners; + gridBBox.cornerVertices( corners.data() ); + + cvf::Vec3d p1_low( corners[0].x(), corners[0].y(), bottomDepth ); + cvf::Vec3d p2_low( corners[1].x(), corners[1].y(), bottomDepth ); + cvf::Vec3d p3_low( corners[2].x(), corners[2].y(), bottomDepth ); + + cvf::Plane lowPlane; + lowPlane.setFromPoints( p1_low, p2_low, p3_low ); + + cvf::Vec3d p1_high( p1_low.x(), p1_low.y(), topDepth ); + cvf::Vec3d p2_high( p2_low.x(), p2_low.y(), topDepth ); + cvf::Vec3d p3_high( p3_low.x(), p3_low.y(), topDepth ); + + cvf::Plane highPlane; + highPlane.setFromPoints( p1_high, p2_high, p3_high ); + highPlane.flip(); + + const auto zAxisDirection = -cvf::Vec3d::Z_AXIS; // NOTE: Negative or positive direction? + const cvf::Vec3d maxHeightVec = zAxisDirection * gridBBox.radius(); + if ( m_polyline.size() > 1 ) + { + const size_t numPoints = m_polyline.size(); + size_t pointIdx = 0; + while ( pointIdx < numPoints - 1 ) + { + size_t nextPointIdx = RivSectionFlattener::indexToNextValidPoint( m_polyline, zAxisDirection, pointIdx ); + if ( nextPointIdx == size_t( -1 ) || nextPointIdx >= m_polyline.size() ) + { + break; + } + + // Start and end point of polyline segment + const cvf::Vec3d p1 = m_polyline[pointIdx]; + const cvf::Vec3d p2 = m_polyline[nextPointIdx]; + + std::vector columnCellCandidates = + createPolylineSegmentCellCandidates( *m_hexGrid, p1, p2, maxHeightVec, topDepth, bottomDepth ); + + cvf::Plane plane; + plane.setFromPoints( p1, p2, p2 + maxHeightVec ); + + // Planes parallel to z-axis for p1 and p2, to prevent triangles outside the polyline segment + cvf::Plane p1Plane; + p1Plane.setFromPoints( p1, p1 + maxHeightVec, p1 + plane.normal() ); + cvf::Plane p2Plane; + p2Plane.setFromPoints( p2, p2 + maxHeightVec, p2 - plane.normal() ); + + std::vector hexPlaneCutTriangleVxes; + hexPlaneCutTriangleVxes.reserve( 5 * 3 ); + std::vector cellFaceForEachTriangleEdge; + cellFaceForEachTriangleEdge.reserve( 5 * 3 ); + cvf::Vec3d cellCorners[8]; + size_t cornerIndices[8]; + for ( const auto globalCellIdx : columnCellCandidates ) + { + if ( ( visibleCells != nullptr ) && ( ( *visibleCells )[globalCellIdx] == 0 ) ) continue; + if ( !m_hexGrid->useCell( globalCellIdx ) ) continue; + + hexPlaneCutTriangleVxes.clear(); + m_hexGrid->cellCornerVertices( globalCellIdx, cellCorners ); + m_hexGrid->cellCornerIndices( globalCellIdx, cornerIndices ); + + // Triangle vertices for polyline segment + caf::HexGridIntersectionTools::planeHexIntersectionMC( plane, + cellCorners, + cornerIndices, + &hexPlaneCutTriangleVxes, + &cellFaceForEachTriangleEdge ); + + // Clip triangles outside the polyline segment using p1 and p2 planes + std::vector clippedTriangleVxes; + std::vector cellFaceForEachClippedTriangleEdge; + + caf::HexGridIntersectionTools::clipTrianglesBetweenTwoParallelPlanes( hexPlaneCutTriangleVxes, + cellFaceForEachTriangleEdge, + p1Plane, + p2Plane, + &clippedTriangleVxes, + &cellFaceForEachClippedTriangleEdge ); + + for ( caf::HexGridIntersectionTools::ClipVx& clvx : clippedTriangleVxes ) + { + if ( !clvx.isVxIdsNative ) clvx.derivedVxLevel = 0; + } + + // Fill triangle vertices vector with clipped triangle vertices + size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; + for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) + { + const size_t vxIdx0 = triangleIdx * 3; + const size_t vxIdx1 = vxIdx0 + 1; + const size_t vxIdx2 = vxIdx0 + 2; + + // Accumulate triangle vertices + cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx ); + cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx ); + cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx ); + + calculatedTriangleVertices.emplace_back( point0 ); + calculatedTriangleVertices.emplace_back( point1 ); + calculatedTriangleVertices.emplace_back( point2 ); + + // TODO: Accumulate mesh lines? + // meshAcc.accumulateMeshLines( cellFaceForEachTriangleEdge, ... + + m_triangleToCellIdxMap.push_back( globalCellIdx ); + } + } + pointIdx = nextPointIdx; + } + } + + m_triangleVxes->assign( calculatedTriangleVertices ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RivPolylineIntersectionGeometryGenerator::createPolylineSegmentCellCandidates( const RivIntersectionHexGridInterface& hexGrid, + const cvf::Vec3d& startPoint, + const cvf::Vec3d& endPoint, + const cvf::Vec3d& heightVector, + const double topDepth, + const double bottomDepth ) +{ + cvf::BoundingBox sectionBBox; + sectionBBox.add( startPoint ); + sectionBBox.add( endPoint ); + sectionBBox.add( startPoint + heightVector ); + sectionBBox.add( startPoint - heightVector ); + sectionBBox.add( endPoint + heightVector ); + sectionBBox.add( endPoint - heightVector ); + + sectionBBox.cutAbove( topDepth ); + sectionBBox.cutBelow( bottomDepth ); + + return hexGrid.findIntersectingCells( sectionBBox ); +} diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h new file mode 100644 index 0000000000..743c3b946c --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -0,0 +1,78 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Statoil ASA +// Copyright (C) Ceetron Solutions AS +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafPdmPointer.h" + +#include "RivIntersectionGeometryGeneratorInterface.h" + +#include "cvfArray.h" + +#include "cvfBoundingBox.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +#include + +#include + +class RigMainGrid; +class RigActiveCellInfo; +class RigResultAccessor; +class RivIntersectionHexGridInterface; +class RimSurface; + +namespace cvf +{ +class ScalarMapper; +class DrawableGeo; +} // namespace cvf + +class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivIntersectionGeometryGeneratorInterface +{ +public: + RivPolylineIntersectionGeometryGenerator( std::vector& polyline, RivIntersectionHexGridInterface* grid ); + ~RivPolylineIntersectionGeometryGenerator() override; + + void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); + + // GeomGen Interface + bool isAnyGeometryPresent() const override; + const std::vector& triangleToCellIndex() const override; + const std::vector& triangleVxToCellCornerInterpolationWeights() const override; + const cvf::Vec3fArray* triangleVxes() const override; + +private: + void calculateArrays( cvf::UByteArray* visibleCells ); + static std::vector createPolylineSegmentCellCandidates( const RivIntersectionHexGridInterface& hexGrid, + const cvf::Vec3d& startPoint, + const cvf::Vec3d& endPoint, + const cvf::Vec3d& heightVector, + const double topDepth, + const double bottomDepth ); + +private: + cvf::ref m_hexGrid; + const std::vector m_polyline; + + // Output arrays + cvf::ref m_triangleVxes; + std::vector m_triangleToCellIdxMap; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 80a74c8e9e..23c3a30e83 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -128,6 +128,8 @@ #include +#pragma optimize( "", off ) + CAF_PDM_XML_SOURCE_INIT( RimEclipseView, "ReservoirView" ); //-------------------------------------------------------------------------------------------------- /// diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index 569e31eddb..caa2ec6150 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -69,8 +69,14 @@ message FenceMeshSection Vec2d endUtmXY = 7; } +//message CutAlongPolylineResponse +//{ + // repeated FenceMeshSection feceMeshSections = 1; + //GridDimensions gridDimensions = 2; +//} + message CutAlongPolylineResponse { - repeated FenceMeshSection feceMeshSections = 1; + repeated float vertexArray = 1; GridDimensions gridDimensions = 2; } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py new file mode 100644 index 0000000000..23e720f30b --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py @@ -0,0 +1,82 @@ +import numpy as np + +import plotly.graph_objects as go + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +grid_file_name = None +fence_poly_line_utm_xy = [11.2631, 11.9276, 14.1083, 18.2929, 18.3523, 10.9173] + +cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( + gridFilename=grid_file_name, + fencePolylineUtmXY=fence_poly_line_utm_xy, +) +cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( + grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) +) + +cut_along_polyline_response.gridDimensions +vertex_array = cut_along_polyline_response.vertexArray + +num_vertex_coords = 3 # [x, y, z] +num_vertices_per_triangle = 3 # [v1, v2, v3] +num_triangles = len(vertex_array) / (num_vertex_coords * num_vertices_per_triangle) + +# Create x-, y-, and z-arrays +x_array = [] +y_array = [] +z_array = [] +for i in range(0, len(vertex_array), num_vertex_coords): + x_array.append(vertex_array[i + 0] ) + y_array.append(vertex_array[i + 1] ) + z_array.append(vertex_array[i + 2] ) + +# Create triangular mesh +i_array = [] +j_array = [] +k_array = [] +for i in range(0, len(x_array), num_vertices_per_triangle): + # Set the indices of the vertices of the triangles + i_array.extend([i + 0]) + j_array.extend([i + 1]) + k_array.extend([i + 2]) + + +fig = go.Figure( + data=[ + go.Mesh3d( + x=x_array, + y=y_array, + z=z_array, + i=i_array, + j=j_array, + k=k_array, + intensity=np.linspace(-5, 5, 1000, endpoint=True), + showscale=True, + colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], + ) + ] +) + +print(f"j array: {j_array}") +print(f"Number of vertices: {len(vertex_array) / 3}") +print(f"Number of traingles: {num_triangles}") +# print(f"Source cell indices array length: {len(source_cell_indices_arr)}") +# print( +# f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" +# ) +# print( +# f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" +# ) +print(fig.data) + +fig.show() diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index fd94e3ff75..ed6bcb2cd5 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -1,6 +1,22 @@ -#include "RiaGrpcGridGeometryExtractionService.h" +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// -// #include "VectorDefines.pb.h" +#include "RiaGrpcGridGeometryExtractionService.h" #include "qstring.h" @@ -9,6 +25,7 @@ #include "RiaGrpcCallbacks.h" #include "RiaGrpcHelper.h" #include "RifReaderSettings.h" +#include "RigActiveCellInfo.h" #include "RigEclipseCaseData.h" #include "RigFemPartCollection.h" #include "RigFemPartGrid.h" @@ -23,7 +40,9 @@ #include "RimGeoMechCase.h" #include "RimGridView.h" #include "RimProject.h" +#include "RivEclipseIntersectionGrid.h" #include "RivGridPartMgr.h" +#include "RivPolylineIntersectionGeometryGenerator.h" #include "RivReservoirPartMgr.h" #include "RivReservoirViewPartMgr.h" @@ -36,6 +55,8 @@ #include "qfileinfo.h" #include "qstring.h" +#pragma optimize( "", off ) + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -46,7 +67,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Reset all pointers resetInternalPointers(); - // Initialize pointer + // Initialize pointers grpc::Status status = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) { @@ -144,7 +165,80 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve const rips::CutAlongPolylineRequest* request, rips::CutAlongPolylineResponse* response ) { - return grpc::Status( grpc::StatusCode::UNIMPLEMENTED, "Not implemented" ); + // Reset all pointers + resetInternalPointers(); + + // Initialize pointers + grpc::Status status = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); + if ( status.error_code() != grpc::StatusCode::OK ) + { + return status; + } + + // Ensure static geometry parts created for grid part manager in view + m_eclipseView->createGridGeometryParts(); + + auto& fencePolyline = request->fencepolylineutmxy(); + if ( fencePolyline.size() < 2 ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Invalid fence polyline" ); + } + + // Convert polyline to vector of cvf::Vec3d + std::vector polyline; + const double zValue = 0.0; + for ( int i = 0; i < fencePolyline.size(); i += 2 ) + { + const double xValue = fencePolyline.Get( i ); + const double yValue = fencePolyline.Get( i + 1 ); + cvf::Vec3d point = cvf::Vec3d( xValue, yValue, zValue ); + polyline.push_back( point ); + } + + RigActiveCellInfo* activeCellInfo = nullptr; // No active cell info for grid + const bool showInactiveCells = true; + RivEclipseIntersectionGrid* eclipseIntersectionGrid = + new RivEclipseIntersectionGrid( m_eclipseView->mainGrid(), activeCellInfo, showInactiveCells ); + + auto* polylineIntersectionGenerator = new RivPolylineIntersectionGeometryGenerator( polyline, eclipseIntersectionGrid ); + + // Handle cell visibilities + const int firstTimeStep = 0; + cvf::UByteArray* visibleCells = new cvf::UByteArray( m_eclipseView->mainGrid()->cellCount() ); + m_eclipseView->calculateCurrentTotalCellVisibility( visibleCells, firstTimeStep ); + + // Loop to count number of visible cells + int numVisibleCells = 0; + for ( size_t i = 0; i < visibleCells->size(); ++i ) + { + if ( ( *visibleCells )[i] != 0 ) + { + ++numVisibleCells; + } + } + + polylineIntersectionGenerator->generateIntersectionGeometry( visibleCells ); + if ( !polylineIntersectionGenerator->isAnyGeometryPresent() ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "No intersection geometry present" ); + } + + const auto& triangleVertices = polylineIntersectionGenerator->triangleVxes(); + if ( triangleVertices->size() == 0 ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No triangle vertices found for polyline" ); + } + + // Set vertex_array and quadindicesarr response + for ( int i = 0; i < triangleVertices->size(); ++i ) + { + const auto& vertex = triangleVertices->get( i ); + response->add_vertexarray( vertex.x() ); + response->add_vertexarray( vertex.y() ); + response->add_vertexarray( vertex.z() ); + } + + return grpc::Status::OK; } //-------------------------------------------------------------------------------------------------- From 1bdc8e95a1da7bb345a44243b99e891dc3656103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Tue, 5 Mar 2024 15:23:41 +0100 Subject: [PATCH 17/45] BACKUP Testing to create enclosing polygon from triangles per cell - WIP --- .../Intersections/CMakeLists_files.cmake | 2 + .../RivEnclosingPolygonGenerator.cpp | 285 ++++++++++++++++++ .../RivEnclosingPolygonGenerator.h | 88 ++++++ ...vPolylineIntersectionGeometryGenerator.cpp | 100 +++++- ...RivPolylineIntersectionGeometryGenerator.h | 9 +- .../GrpcProtos/GridGeometryExtraction.proto | 10 +- ..._geometry_extraction_cut_along_polyline.py | 190 ++++++++++++ ...n_cut_along_polyline_TRIANGLE_VERTICES.py} | 32 +- ...d_geometry_extraction_get_grid_surface.py} | 3 +- .../RiaGrpcGridGeometryExtractionService.cpp | 60 +++- 10 files changed, 735 insertions(+), 44 deletions(-) create mode 100644 ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp create mode 100644 ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py rename GrpcInterface/Python/rips/WebvizPythonExamples/{grid_geometry_extraction_intersection.py => grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py} (73%) rename GrpcInterface/Python/rips/WebvizPythonExamples/{grid_geometry_extraction.py => grid_geometry_extraction_get_grid_surface.py} (93%) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake b/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake index 11e8c43463..4e2ce674c9 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake +++ b/ApplicationLibCode/ModelVisualization/Intersections/CMakeLists_files.cmake @@ -12,6 +12,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RivFemIntersectionGrid.h ${CMAKE_CURRENT_LIST_DIR}/RivIntersectionGeometryGeneratorInterface.h ${CMAKE_CURRENT_LIST_DIR}/RivPolylineIntersectionGeometryGenerator.h + ${CMAKE_CURRENT_LIST_DIR}/RivEnclosingPolygonGenerator.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -26,6 +27,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RivEclipseIntersectionGrid.cpp ${CMAKE_CURRENT_LIST_DIR}/RivFemIntersectionGrid.cpp ${CMAKE_CURRENT_LIST_DIR}/RivPolylineIntersectionGeometryGenerator.cpp + ${CMAKE_CURRENT_LIST_DIR}/RivEnclosingPolygonGenerator.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp new file mode 100644 index 0000000000..bd4f9eac1a --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -0,0 +1,285 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RivEnclosingPolygonGenerator.h" +#include "cvfMath.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PolygonVertexWelder::PolygonVertexWelder( double weldEpsilon ) + : m_epsilon( weldEpsilon ) + , m_first( cvf::UNDEFINED_UINT ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PolygonVertexWelder::reserveVertices( cvf::uint vertexCount ) +{ + m_vertex.reserve( vertexCount ); + m_next.reserve( vertexCount ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector PolygonVertexWelder::weldVerticesAndGetIndices( const std::vector& vertices ) +{ + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3f& vertex ) +{ + // Compute cell coordinates of bounding box of vertex epsilon neighborhood + int left = static_cast( ( vertex.x() - m_epsilon ) ); + int right = static_cast( ( vertex.x() + m_epsilon ) ); + int front = static_cast( ( vertex.y() - m_epsilon ) ); + int back = static_cast( ( vertex.y() + m_epsilon ) ); + int bottom = static_cast( ( vertex.z() - m_epsilon ) ); + int top = static_cast( ( vertex.z() + m_epsilon ) ); + + // Call function to step through linked list of bucket, testing + // if vertex is within the epsilon of one of the vertices in the bucket + cvf::uint indexOfLocatedVertex = locateVertexInPolygon( vertex ); + if ( indexOfLocatedVertex != cvf::UNDEFINED_UINT ) + { + // if ( wasWelded ) *wasWelded = true; + return indexOfLocatedVertex; + } + + // Vertex not found in epsilon neighborhood, add it to the list + cvf::uint indexOfAddedVertex = addVertexToPolygon( vertex ); + return indexOfAddedVertex; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const cvf::Vec3f& PolygonVertexWelder::vertex( cvf::uint index ) const +{ + return m_vertex[index]; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref PolygonVertexWelder::createVertexArray() const +{ + cvf::ref vertexArray = new cvf::Vec3fArray( m_vertex ); + return vertexArray; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3f& vertex ) const +{ + const auto epsilonSquared = m_epsilon * m_epsilon; + + cvf::uint currentIndex = m_first; + while ( currentIndex != cvf::UNDEFINED_UINT ) + { + // Weld point within tolerance + float distanceSquared = ( m_vertex[currentIndex] - vertex ).lengthSquared(); + if ( distanceSquared < epsilonSquared ) + { + return currentIndex; + } + currentIndex = m_next[currentIndex]; + } + + // No vertex found to weld to + return cvf::UNDEFINED_UINT; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::uint PolygonVertexWelder::addVertexToPolygon( const cvf::Vec3f& vertex ) +{ + // Add vertex and update linked list + m_vertex.push_back( vertex ); + m_next.push_back( m_first ); + CVF_TIGHT_ASSERT( m_vertex.size() == m_next.size() ); + + // Update index of first vertex + cvf::uint indexOfAddedVertex = static_cast( m_vertex.size() - 1 ); + m_first = indexOfAddedVertex; + + return indexOfAddedVertex; +} + +//-------------------------------------------------------------------------------------------------- +/// +/// ************************************************************************************************ +/// ************************************************************************************************ +/// ************************************************************************************************ +/// ************************************************************************************************ +/// +//-------------------------------------------------------------------------------------------------- + +RivEnclosingPolygonGenerator::RivEnclosingPolygonGenerator() + : m_polygonVertexWelder( 1e-6 ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivEnclosingPolygonGenerator::constructEnclosingPolygon() +{ + // Construct the enclosing polygon from the edges + // + // d ________ c + // | /| + // | / | + // | / | + // | / | + // | / | + // |/_____| + // a b + // + // The line segment ca/ac is the only edge that is not part of the enclosing polygon + // This line segment will occur twice in the list of edges as it is present in both triangles + // (a, b, c) and (a, c, d). + // The line segment ca/ac will be removed from the list of for the enclosing polygon + // + // Enclosing edges are defined as edges only occurring once in the list of edges + // + + // Must have at least 3 edges to construct a polygon + CVF_ASSERT( m_allEdgeKeys.size() >= 3 ); + + // Map of edge key and number of occurrences + std::map edgeKeysAndCount; + + // Extract boundary edge keys from all edge keys + for ( const auto& edgeKey : m_allEdgeKeys ) + { + // If edge is already in the set, it occurs more than once and is not a boundary edge + if ( edgeKeysAndCount.contains( edgeKey ) ) + { + edgeKeysAndCount[edgeKey]++; + } + else + { + edgeKeysAndCount[edgeKey] = 1; + } + } + + // At least a triangle is needed to construct a polygon + CVF_ASSERT( edgeKeysAndCount.size() >= 3 ); // This occurs to often? + + // Extract boundary edge keys from all edge keys and count + std::set boundaryEdges; + for ( const auto& [key, value] : edgeKeysAndCount ) + { + if ( value == 1 ) + { + boundaryEdges.insert( cvf::EdgeKey::fromkeyVal( key ) ); + } + } + + // Lambda function to check if index exists in a vector + auto indexExists = []( const std::vector& indices, cvf::uint index ) -> bool + { return std::find( indices.cbegin(), indices.cend(), index ) != indices.cend(); }; + + // Construct the enclosing polygon from the boundary edges + cvf::EdgeKey currentEdge = *boundaryEdges.begin(); + std::vector enclosingPolygonVertexIndices = { currentEdge.index1(), currentEdge.index2() }; + cvf::uint nextVertexIndex = currentEdge.index2(); + boundaryEdges.erase( currentEdge ); + while ( !boundaryEdges.empty() ) + { + // Find next edge in the boundary, i.e. edge containing the next vertex index to look for + currentEdge = findNextEdge( nextVertexIndex, boundaryEdges ); + boundaryEdges.erase( currentEdge ); + const int start = currentEdge.index1(); + const int end = currentEdge.index2(); + if ( start == cvf::UNDEFINED_UINT || end == cvf::UNDEFINED_UINT ) + { + break; + } + + // The enclosing polygon is a closed loop, so the start and end vertices are always in the correct order + if ( !indexExists( enclosingPolygonVertexIndices, end ) ) + { + nextVertexIndex = end; + enclosingPolygonVertexIndices.push_back( end ); + } + else if ( !indexExists( enclosingPolygonVertexIndices, start ) ) + { + nextVertexIndex = start; + enclosingPolygonVertexIndices.push_back( start ); + } + } + + // Convert vertex indices to vertices + m_polygonVertices.clear(); + for ( cvf::uint vertexIndex : enclosingPolygonVertexIndices ) + { + m_polygonVertices.push_back( m_polygonVertexWelder.vertex( vertexIndex ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::EdgeKey RivEnclosingPolygonGenerator::findNextEdge( int vertexIndex, const std::set& boundaryEdges ) +{ + for ( auto& elm : boundaryEdges ) + { + if ( elm.index1() == vertexIndex || elm.index2() == vertexIndex ) + { + return elm; + } + } + + // Return a dummy edge to indicate no next edge found + return cvf::EdgeKey( cvf::UNDEFINED_UINT, cvf::UNDEFINED_UINT ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RivEnclosingPolygonGenerator::getPolygonVertices() const +{ + return m_polygonVertices; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RivEnclosingPolygonGenerator::addTriangleVertices( const cvf::Vec3f& p0, const cvf::Vec3f& p1, const cvf::Vec3f& p2 ) +{ + cvf::uint i0 = m_polygonVertexWelder.weldVertexAndGetIndex( p0 ); + cvf::uint i1 = m_polygonVertexWelder.weldVertexAndGetIndex( p1 ); + cvf::uint i2 = m_polygonVertexWelder.weldVertexAndGetIndex( p2 ); + + // Add edges keys to list of all edges + m_allEdgeKeys.emplace_back( cvf::EdgeKey( i0, i1 ).toKeyVal() ); + m_allEdgeKeys.emplace_back( cvf::EdgeKey( i1, i2 ).toKeyVal() ); + m_allEdgeKeys.emplace_back( cvf::EdgeKey( i2, i0 ).toKeyVal() ); +} diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h new file mode 100644 index 0000000000..e9c362ce8d --- /dev/null +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2018- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafLine.h" +#include "cvfArray.h" +#include "cvfEdgeKey.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +#include +#include + +/* + * Class for handling welding of vertices in a polygon to prevent duplicated vertex 3D points within a tolerance margin + */ +class PolygonVertexWelder +{ +public: + PolygonVertexWelder( double weldEpsilon ); + + void reserveVertices( cvf::uint vertexCount ); + + // Add a vertex to the welder. If the vertex is within the tolerance of an existing vertex, the existing vertex index is returned + // Size of returned index array is equal size of input array + std::vector weldVerticesAndGetIndices( const std::vector& vertices ); // TODO: Remove? + cvf::uint weldVertexAndGetIndex( const cvf::Vec3f& vertex ); + + const cvf::Vec3f& vertex( cvf::uint index ) const; + cvf::ref createVertexArray() const; + +private: + cvf::uint locateVertexInPolygon( const cvf::Vec3f& vertex ) const; + cvf::uint addVertexToPolygon( const cvf::Vec3f& vertex ); + +private: + const double m_epsilon; // Tolerance for vertex welding, radius around vertex defining welding neighborhood + + cvf::uint m_first; // Start of linked list + std::vector m_next; // Links each vertex to next in linked list. Always numVertices long, will grow as vertices are added + std::vector m_vertex; // Unique vertices within tolerance +}; + +/* + * Class for generating an enclosing polygon from a set of vertices. + * + * The class will weld triangle vertices close to each other and provide a vertex index for + * the resulting set of vertices. These indices are used for algorithms constructing the enclosing polygon. + * + * The welding is done using a tolerance value to handle floating point errors. + */ +class RivEnclosingPolygonGenerator +{ +public: + RivEnclosingPolygonGenerator(); + + std::vector getPolygonVertices() const; + + bool isValidPolygon() const { return m_allEdgeKeys.size() >= size_t( 3 ); } + size_t numEdges() const { return m_allEdgeKeys.size(); } + + void addTriangleVertices( const cvf::Vec3f& p0, const cvf::Vec3f& p1, const cvf::Vec3f& p2 ); + void constructEnclosingPolygon(); + +private: + static cvf::EdgeKey findNextEdge( int vertextIndex, const std::set& boundaryEdges ); + +private: + PolygonVertexWelder m_polygonVertexWelder; // Add and weld vertices for a polygon, provides vertex index + std::vector m_allEdgeKeys; // Create edge defined by vertex indices when adding triangle. Using cvf::EdgeKey::toKeyVal() + std::vector m_polygonVertices; // List polygon vertices counter clock-wise +}; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index 4d47ee1115..48e2ef0b96 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -18,12 +18,15 @@ #include "RivPolylineIntersectionGeometryGenerator.h" +#include "RivEnclosingPolygonGenerator.h" #include "RivIntersectionHexGridInterface.h" #include "RivSectionFlattener.h" #include "cafHexGridIntersectionTools/cafHexGridIntersectionTools.h" +#include "cafLine.h" #include "cvfPlane.h" +#include "cvfVertexWelder.h" #pragma optimize( "", off ) @@ -35,7 +38,8 @@ RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerat : m_polyline( polyline ) , m_hexGrid( grid ) { - m_triangleVxes = new cvf::Vec3fArray; + m_triangleVxes = new cvf::Vec3fArray; + m_polygonVertices = new cvf::Vec3fArray; } //-------------------------------------------------------------------------------------------------- @@ -50,7 +54,8 @@ RivPolylineIntersectionGeometryGenerator::~RivPolylineIntersectionGeometryGenera //-------------------------------------------------------------------------------------------------- bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const { - return m_triangleVxes->size() > 0; + return m_polygonVertices->size() > 0; + // return m_triangleVxes->size() > 0; } //-------------------------------------------------------------------------------------------------- @@ -76,12 +81,39 @@ const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::triangleVxes() //-------------------------------------------------------------------------------------------------- const std::vector& RivPolylineIntersectionGeometryGenerator::triangleVxToCellCornerInterpolationWeights() const { - CVF_ASSERT( m_triangleVxes->size() > 0 ); + CVF_ASSERT( false ); // Not implemented error return {}; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::polygonVxes() const +{ + CVF_ASSERT( m_polygonVertices->size() > 0 ); + return m_polygonVertices.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RivPolylineIntersectionGeometryGenerator::vertiesPerPolygon() const +{ + CVF_ASSERT( m_verticesPerPolygon.size() > 0 ); + return m_verticesPerPolygon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RivPolylineIntersectionGeometryGenerator::polygonToCellIndex() const +{ + CVF_ASSERT( m_polygonToCellIdxMap.size() > 0 ); + return m_polygonToCellIdxMap; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -95,11 +127,10 @@ void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf //-------------------------------------------------------------------------------------------------- void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) { - if ( m_triangleVxes->size() != 0 || m_hexGrid.isNull() ) return; + if ( m_triangleVxes->size() != 0 || m_polygonVertices->size() != 0 || m_hexGrid.isNull() ) return; std::vector calculatedTriangleVertices; - - // MeshLinesAccumulator meshAcc( m_hexGrid.p() ); + std::vector calculatedPolygonVertices; cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); @@ -142,6 +173,7 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const cvf::Vec3d p1 = m_polyline[pointIdx]; const cvf::Vec3d p2 = m_polyline[nextPointIdx]; + // Get cell candidates for the polyline segment (subset of global cells) std::vector columnCellCandidates = createPolylineSegmentCellCandidates( *m_hexGrid, p1, p2, maxHeightVec, topDepth, bottomDepth ); @@ -154,17 +186,22 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* cvf::Plane p2Plane; p2Plane.setFromPoints( p2, p2 + maxHeightVec, p2 - plane.normal() ); + // Placeholder for triangle vertices per cell std::vector hexPlaneCutTriangleVxes; hexPlaneCutTriangleVxes.reserve( 5 * 3 ); std::vector cellFaceForEachTriangleEdge; cellFaceForEachTriangleEdge.reserve( 5 * 3 ); cvf::Vec3d cellCorners[8]; size_t cornerIndices[8]; + + // Handle triangles per cell for ( const auto globalCellIdx : columnCellCandidates ) { if ( ( visibleCells != nullptr ) && ( ( *visibleCells )[globalCellIdx] == 0 ) ) continue; if ( !m_hexGrid->useCell( globalCellIdx ) ) continue; + // if ( globalCellIdx != 93996 ) continue; + hexPlaneCutTriangleVxes.clear(); m_hexGrid->cellCornerVertices( globalCellIdx, cellCorners ); m_hexGrid->cellCornerIndices( globalCellIdx, cornerIndices ); @@ -176,7 +213,19 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* &hexPlaneCutTriangleVxes, &cellFaceForEachTriangleEdge ); - // Clip triangles outside the polyline segment using p1 and p2 planes + // DEBUG CODE + bool tmp = false; + if ( hexPlaneCutTriangleVxes.size() < 3 ) + { + tmp = true; + } + if ( globalCellIdx == 93996 ) + { + tmp = true; + } + // END DEBUG CODE + + // Clip triangles outside the polyline segment using the planes for point p1 and p2 std::vector clippedTriangleVxes; std::vector cellFaceForEachClippedTriangleEdge; @@ -192,6 +241,9 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* if ( !clvx.isVxIdsNative ) clvx.derivedVxLevel = 0; } + // Object to for adding triangle vertices, well vertices and generate polygon vertices + RivEnclosingPolygonGenerator enclosingPolygonGenerator; + // Fill triangle vertices vector with clipped triangle vertices size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) @@ -200,26 +252,46 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const size_t vxIdx1 = vxIdx0 + 1; const size_t vxIdx2 = vxIdx0 + 2; - // Accumulate triangle vertices - cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx ); - cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx ); - cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx ); + const cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx ); + const cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx ); + const cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx ); calculatedTriangleVertices.emplace_back( point0 ); calculatedTriangleVertices.emplace_back( point1 ); calculatedTriangleVertices.emplace_back( point2 ); - // TODO: Accumulate mesh lines? - // meshAcc.accumulateMeshLines( cellFaceForEachTriangleEdge, ... + // Add triangle to enclosing polygon line handler + enclosingPolygonGenerator.addTriangleVertices( point0, point1, point2 ); + } + + // Must be a triangle + if ( enclosingPolygonGenerator.numEdges() < size_t( 3 ) ) + { + continue; + } - m_triangleToCellIdxMap.push_back( globalCellIdx ); + // Construct enclosing polygon after adding each triangle + enclosingPolygonGenerator.constructEnclosingPolygon(); + const auto& vertices = enclosingPolygonGenerator.getPolygonVertices(); + for ( const auto& vertex : enclosingPolygonGenerator.getPolygonVertices() ) + { + calculatedPolygonVertices.push_back( vertex ); } + + m_verticesPerPolygon.push_back( vertices.size() ); + m_polygonToCellIdxMap.push_back( globalCellIdx ); + + // TODO: + // - Create polygon + // - Get polygon indices + // - Convert to "local" coordinates for each polyline segment } pointIdx = nextPointIdx; } } m_triangleVxes->assign( calculatedTriangleVertices ); + m_polygonVertices->assign( calculatedPolygonVertices ); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index 743c3b946c..a1d63b47ee 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -51,7 +51,10 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI RivPolylineIntersectionGeometryGenerator( std::vector& polyline, RivIntersectionHexGridInterface* grid ); ~RivPolylineIntersectionGeometryGenerator() override; - void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); + void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); + const cvf::Vec3fArray* polygonVxes() const; + const std::vector& vertiesPerPolygon() const; + const std::vector& polygonToCellIndex() const; // GeomGen Interface bool isAnyGeometryPresent() const override; @@ -75,4 +78,8 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI // Output arrays cvf::ref m_triangleVxes; std::vector m_triangleToCellIdxMap; + + std::vector m_polygonToCellIdxMap; + cvf::ref m_polygonVertices; + std::vector m_verticesPerPolygon; }; diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index caa2ec6150..a164a8d494 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -1,6 +1,5 @@ syntax = "proto3"; -import "Grid.proto"; import "VectorDefines.proto"; // Will this work if we import only part of the protos? @@ -48,7 +47,7 @@ message GetGridSurfaceResponse repeated float vertexArray = 1; repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long - GridDimensions gridDimensions = 5; + Vec3i gridDimensions = 5; Vec3d originUtm = 6; } @@ -72,11 +71,12 @@ message FenceMeshSection //message CutAlongPolylineResponse //{ // repeated FenceMeshSection feceMeshSections = 1; - //GridDimensions gridDimensions = 2; + //Vec3i gridDimensions = 2; //} message CutAlongPolylineResponse { - repeated float vertexArray = 1; - GridDimensions gridDimensions = 2; + repeated float polygonVertexArray = 1; + repeated fixed32 verticesPerPolygonArr = 2; // Number of vertices per polygon, numPolygons long + repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per polygon, numPolygons long } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py new file mode 100644 index 0000000000..dea4561f4a --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -0,0 +1,190 @@ +import numpy as np + +import plotly.graph_objects as go + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +grid_file_name = None +grid_file_name = "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + +# Test polylines +mocked_model_fence_poly_line_utm_xy = [11.2631, 11.9276, 14.1083, 18.2929, 18.3523, 10.9173] +norne_case_fence_poly_line_utm_xy = [456221, 7.32113e+06, 457150, 7.32106e+06, 456885, 7.32176e+06, 457648, 7.3226e+06, 458805, 7.32278e+06] +norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e+06, 456885, 7.32176e+06] +norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e+06, 459279, 7.32477e+06] + + +fence_poly_line_utm_xy = norne_case_single_segment_poly_line_utm_xy + +cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( + gridFilename=grid_file_name, + fencePolylineUtmXY=fence_poly_line_utm_xy, +) +cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( + grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) +) + +polygon_vertex_array_org = cut_along_polyline_response.polygonVertexArray +vertices_per_polygon = cut_along_polyline_response.verticesPerPolygonArr +source_cell_indices = cut_along_polyline_response.sourceCellIndicesArr + +x_start = polygon_vertex_array_org[0] +y_start = polygon_vertex_array_org[1] +z_start = polygon_vertex_array_org[2] + +# Subtract x_start, y_start, z_start from all x, y, z coordinates +polygon_vertex_array = [] +for i in range(0, len(polygon_vertex_array_org), 3): + polygon_vertex_array.extend([polygon_vertex_array_org[i] - x_start, polygon_vertex_array_org[i + 1] - y_start, polygon_vertex_array_org[i + 2] - z_start]) + +num_vertex_coords = 3 # [x, y, z] + +# Create x-, y-, and z-arrays +x_array = [] +y_array = [] +z_array = [] +for i in range(0, len(polygon_vertex_array), num_vertex_coords): + # vertex array is provided as a single array of x, y, z coordinates + # i.e. [x1, y1, z1, x2, y2, z2, x3, y3, z3, ... , xn, yn, zn] + x_array.append(polygon_vertex_array[i + 0] ) + y_array.append(polygon_vertex_array[i + 1] ) + z_array.append(polygon_vertex_array[i + 2] ) + +# Create triangular mesh +vertices = np.array(polygon_vertex_array).reshape(-1, 3) + +# Create mesh data +x, y, z = vertices.T +i = [] +j = [] +k = [] + +# Create edges between points in triangles +triangle_edges_x = [] +triangle_edges_y = [] +triangle_edges_z = [] + +# Populate i, j, k based on vertices_per_polygon +# Create triangles from each polygon +# A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] +# A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] + +polygon_v0_idx = 0 # Index of vertex 0 in the polygon +for vertex_count in vertices_per_polygon: + # Must have at least one triangle + if vertex_count < 3: + polygon_v0_idx += vertex_count + continue + + indices = list(range(polygon_v0_idx, polygon_v0_idx + vertex_count)) + + # Build triangles from polygon + num_triangles = vertex_count - 2 + for triangle_index in range(0, num_triangles): + triangle_v0_idx = polygon_v0_idx + triangle_v1_idx = indices[triangle_index + 1] + triangle_v2_idx = indices[triangle_index + 2] + + # Vertex indices for the triangle + i.append(triangle_v0_idx) + j.append(triangle_v1_idx) + k.append(triangle_v2_idx) + + # Create edge between vertices in triangle with x,y,z coordinates, coordinates per vertex is 3 + coordinate_step = 3 # step per vertex + triangle_v0_global_idx = triangle_v0_idx * coordinate_step + triangle_v1_global_idx = triangle_v1_idx * coordinate_step + triangle_v2_global_idx = triangle_v2_idx * coordinate_step + + # Add x,y,z coordinates for the triangle vertices (closing triangle with 'None') + triangle_edges_x.extend([polygon_vertex_array[triangle_v0_global_idx + 0], polygon_vertex_array[triangle_v1_global_idx + 0], polygon_vertex_array[triangle_v2_global_idx + 0], polygon_vertex_array[triangle_v0_global_idx + 0], None]) + triangle_edges_y.extend([polygon_vertex_array[triangle_v0_global_idx + 1], polygon_vertex_array[triangle_v1_global_idx + 1], polygon_vertex_array[triangle_v2_global_idx + 1], polygon_vertex_array[triangle_v0_global_idx + 1], None]) + triangle_edges_z.extend([polygon_vertex_array[triangle_v0_global_idx + 2], polygon_vertex_array[triangle_v1_global_idx + 2], polygon_vertex_array[triangle_v2_global_idx + 2], polygon_vertex_array[triangle_v0_global_idx + 2], None]) + + # Move to next polygon + polygon_v0_idx += vertex_count + +# Create edges between points in polygons +polygon_edges_x = [] +polygon_edges_y = [] +polygon_edges_z = [] +polygon_global_start_index = 0 +coordinate_step = 3 # step per vertex +for vertex_count in vertices_per_polygon: + # Must have at least a triangle + if vertex_count < 3: + polygon_global_start_index += vertex_count * coordinate_step + continue + + for vertex_idx in range(0, vertex_count): + vertex_global_idx = polygon_global_start_index + vertex_idx * coordinate_step + polygon_edges_x.append(polygon_vertex_array[vertex_global_idx + 0]) + polygon_edges_y.append(polygon_vertex_array[vertex_global_idx + 1]) + polygon_edges_z.append(polygon_vertex_array[vertex_global_idx + 2]) + + # Close the polygon + polygon_edges_x.append(polygon_vertex_array[polygon_global_start_index + 0]) + polygon_edges_y.append(polygon_vertex_array[polygon_global_start_index + 1]) + polygon_edges_z.append(polygon_vertex_array[polygon_global_start_index + 2]) + + polygon_edges_x.append(None) + polygon_edges_y.append(None) + polygon_edges_z.append(None) + + polygon_global_start_index += vertex_count * coordinate_step + + + +# Create mesh +mesh_3D = go.Mesh3d(x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color='rgba(244,22,100,0.6)') + +# Create edge lines for triangles +triangle_edges_3d = go.Scatter3d( + x=triangle_edges_x, + y=triangle_edges_y, + z=triangle_edges_z, + mode='lines', + name='', + line=dict(color= 'rgb(0,0,0)', width=1) +) + +# Create outer edge lines for polygon +polygon_edges_3d = go.Scatter3d( + x=polygon_edges_x, + y=polygon_edges_y, + z=polygon_edges_z, + mode='lines', + name='', + line=dict(color= 'rgb(0,0,0)', width=1) +) + +fig = go.Figure( + data=[ + mesh_3D, + # triangle_edges_3d, + polygon_edges_3d + ] +) + +# print(f"j array: {j_array}") +# print(f"Number of vertices: {len(vertex_array) / 3}") +# print(f"Number of traingles: {num_triangles}") +# print(f"Source cell indices array length: {len(source_cell_indices_arr)}") +# print( +# f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" +# ) +# print( +# f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" +# ) +print(fig.data) + +fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py similarity index 73% rename from GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py rename to GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py index 23e720f30b..da05c5ee47 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_intersection.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py @@ -24,8 +24,7 @@ grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) ) -cut_along_polyline_response.gridDimensions -vertex_array = cut_along_polyline_response.vertexArray +vertex_array = cut_along_polyline_response.triangleVertexArray num_vertex_coords = 3 # [x, y, z] num_vertices_per_triangle = 3 # [v1, v2, v3] @@ -50,10 +49,7 @@ j_array.extend([i + 1]) k_array.extend([i + 2]) - -fig = go.Figure( - data=[ - go.Mesh3d( +mesh_3d = go.Mesh3d( x=x_array, y=y_array, z=z_array, @@ -64,6 +60,30 @@ showscale=True, colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], ) + +# Create edges between points in triangles +Xe = [] +Ye = [] +Ze = [] +step_per_triangle = num_vertex_coords * num_vertices_per_triangle +for i in range(0, len(vertex_array), step_per_triangle): + Xe.extend([vertex_array[i + 0], vertex_array[i + 3], vertex_array[i + 6], None]) # x-coordinates of start and end points of the edge + Ye.extend([vertex_array[i + 1], vertex_array[i + 4], vertex_array[i + 7], None]) # y-coordinates of start and end points of the edge + Ze.extend([vertex_array[i + 2], vertex_array[i + 5], vertex_array[i + 8], None]) # z-coordinates of start and end points of the edge + +edges_3d = go.Scatter3d( + x=Xe, + y=Ye, + z=Ze, + mode='lines', + name='', + line=dict(color= 'rgb(70,70,70)', width=1) +) + +fig = go.Figure( + data=[ + mesh_3d, + edges_3d ] ) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py similarity index 93% rename from GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py rename to GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 996fba8178..a168b31688 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -25,7 +25,6 @@ grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) ) -get_grid_surface_response.gridDimensions vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr origin_utm = get_grid_surface_response.originUtm @@ -78,7 +77,7 @@ f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" ) print( - f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" + f"Grid dimensions [I, J, K]: [{grid_dimensions.i}, {grid_dimensions.j}, {grid_dimensions.k}]" ) print(fig.data) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index ed6bcb2cd5..eb29fe5154 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -137,16 +137,14 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } // Set grid dimensions - const auto countI = m_eclipseView->mainGrid()->cellCountI(); - const auto countJ = m_eclipseView->mainGrid()->cellCountJ(); - const auto countK = m_eclipseView->mainGrid()->cellCountK(); - rips::Vec3i* dimensions = new rips::Vec3i; - rips::GridDimensions* gridDimensions = new rips::GridDimensions; + const auto countI = m_eclipseView->mainGrid()->cellCountI(); + const auto countJ = m_eclipseView->mainGrid()->cellCountJ(); + const auto countK = m_eclipseView->mainGrid()->cellCountK(); + rips::Vec3i* dimensions = new rips::Vec3i; dimensions->set_i( countI ); dimensions->set_j( countJ ); dimensions->set_k( countK ); - gridDimensions->set_allocated_dimensions( dimensions ); - response->set_allocated_griddimensions( gridDimensions ); + response->set_allocated_griddimensions( dimensions ); // Close project and return if ( m_application != nullptr ) @@ -217,25 +215,55 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } } + // Generate intersection polylineIntersectionGenerator->generateIntersectionGeometry( visibleCells ); if ( !polylineIntersectionGenerator->isAnyGeometryPresent() ) { return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "No intersection geometry present" ); } - const auto& triangleVertices = polylineIntersectionGenerator->triangleVxes(); - if ( triangleVertices->size() == 0 ) + // Get results + // const auto& triangleVertices = polylineIntersectionGenerator->triangleVxes(); + // if ( triangleVertices->size() == 0 ) + //{ + // return grpc::Status( grpc::StatusCode::NOT_FOUND, "No triangle vertices found for polyline" ); + //} + + //// Set vertex_array and quadindicesarr response + // for ( int i = 0; i < triangleVertices->size(); ++i ) + //{ + // const auto& vertex = triangleVertices->get( i ); + // response->add_trianglevertexarray( vertex.x() ); + // response->add_trianglevertexarray( vertex.y() ); + // response->add_trianglevertexarray( vertex.z() ); + // } + + // Polygon vertices + const auto& polygonVertices = polylineIntersectionGenerator->polygonVxes(); + if ( polygonVertices->size() == 0 ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No triangle vertices found for polyline" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); + } + for ( int i = 0; i < polygonVertices->size(); ++i ) + { + const auto& vertex = polygonVertices->get( i ); + response->add_polygonvertexarray( vertex.x() ); + response->add_polygonvertexarray( vertex.y() ); + response->add_polygonvertexarray( vertex.z() ); } - // Set vertex_array and quadindicesarr response - for ( int i = 0; i < triangleVertices->size(); ++i ) + // Vertices per polygon + const auto& verticesPerPolygon = polylineIntersectionGenerator->vertiesPerPolygon(); + for ( const auto& elm : verticesPerPolygon ) { - const auto& vertex = triangleVertices->get( i ); - response->add_vertexarray( vertex.x() ); - response->add_vertexarray( vertex.y() ); - response->add_vertexarray( vertex.z() ); + response->add_verticesperpolygonarr( static_cast( elm ) ); + } + + // Polygon to cell indices + const auto& polygonCellIndices = polylineIntersectionGenerator->polygonToCellIndex(); + for ( const auto& elm : polygonCellIndices ) + { + response->add_sourcecellindicesarr( static_cast( elm ) ); } return grpc::Status::OK; From de3a00a95793bcef252586f8ff902a46c00af649 Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Tue, 5 Mar 2024 14:24:28 +0000 Subject: [PATCH 18/45] Python code linting changes detected by black --- ..._geometry_extraction_cut_along_polyline.py | 103 +++++++++++++----- ...on_cut_along_polyline_TRIANGLE_VERTICES.py | 52 ++++----- 2 files changed, 101 insertions(+), 54 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index dea4561f4a..0dec245101 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -14,13 +14,33 @@ grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) grid_file_name = None -grid_file_name = "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +grid_file_name = ( + "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +) # Test polylines -mocked_model_fence_poly_line_utm_xy = [11.2631, 11.9276, 14.1083, 18.2929, 18.3523, 10.9173] -norne_case_fence_poly_line_utm_xy = [456221, 7.32113e+06, 457150, 7.32106e+06, 456885, 7.32176e+06, 457648, 7.3226e+06, 458805, 7.32278e+06] -norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e+06, 456885, 7.32176e+06] -norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e+06, 459279, 7.32477e+06] +mocked_model_fence_poly_line_utm_xy = [ + 11.2631, + 11.9276, + 14.1083, + 18.2929, + 18.3523, + 10.9173, +] +norne_case_fence_poly_line_utm_xy = [ + 456221, + 7.32113e06, + 457150, + 7.32106e06, + 456885, + 7.32176e06, + 457648, + 7.3226e06, + 458805, + 7.32278e06, +] +norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.32176e06] +norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] fence_poly_line_utm_xy = norne_case_single_segment_poly_line_utm_xy @@ -44,7 +64,13 @@ # Subtract x_start, y_start, z_start from all x, y, z coordinates polygon_vertex_array = [] for i in range(0, len(polygon_vertex_array_org), 3): - polygon_vertex_array.extend([polygon_vertex_array_org[i] - x_start, polygon_vertex_array_org[i + 1] - y_start, polygon_vertex_array_org[i + 2] - z_start]) + polygon_vertex_array.extend( + [ + polygon_vertex_array_org[i] - x_start, + polygon_vertex_array_org[i + 1] - y_start, + polygon_vertex_array_org[i + 2] - z_start, + ] + ) num_vertex_coords = 3 # [x, y, z] @@ -55,9 +81,9 @@ for i in range(0, len(polygon_vertex_array), num_vertex_coords): # vertex array is provided as a single array of x, y, z coordinates # i.e. [x1, y1, z1, x2, y2, z2, x3, y3, z3, ... , xn, yn, zn] - x_array.append(polygon_vertex_array[i + 0] ) - y_array.append(polygon_vertex_array[i + 1] ) - z_array.append(polygon_vertex_array[i + 2] ) + x_array.append(polygon_vertex_array[i + 0]) + y_array.append(polygon_vertex_array[i + 1]) + z_array.append(polygon_vertex_array[i + 2]) # Create triangular mesh vertices = np.array(polygon_vertex_array).reshape(-1, 3) @@ -78,7 +104,7 @@ # A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] # A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] -polygon_v0_idx = 0 # Index of vertex 0 in the polygon +polygon_v0_idx = 0 # Index of vertex 0 in the polygon for vertex_count in vertices_per_polygon: # Must have at least one triangle if vertex_count < 3: @@ -100,15 +126,39 @@ k.append(triangle_v2_idx) # Create edge between vertices in triangle with x,y,z coordinates, coordinates per vertex is 3 - coordinate_step = 3 # step per vertex + coordinate_step = 3 # step per vertex triangle_v0_global_idx = triangle_v0_idx * coordinate_step triangle_v1_global_idx = triangle_v1_idx * coordinate_step - triangle_v2_global_idx = triangle_v2_idx * coordinate_step - + triangle_v2_global_idx = triangle_v2_idx * coordinate_step + # Add x,y,z coordinates for the triangle vertices (closing triangle with 'None') - triangle_edges_x.extend([polygon_vertex_array[triangle_v0_global_idx + 0], polygon_vertex_array[triangle_v1_global_idx + 0], polygon_vertex_array[triangle_v2_global_idx + 0], polygon_vertex_array[triangle_v0_global_idx + 0], None]) - triangle_edges_y.extend([polygon_vertex_array[triangle_v0_global_idx + 1], polygon_vertex_array[triangle_v1_global_idx + 1], polygon_vertex_array[triangle_v2_global_idx + 1], polygon_vertex_array[triangle_v0_global_idx + 1], None]) - triangle_edges_z.extend([polygon_vertex_array[triangle_v0_global_idx + 2], polygon_vertex_array[triangle_v1_global_idx + 2], polygon_vertex_array[triangle_v2_global_idx + 2], polygon_vertex_array[triangle_v0_global_idx + 2], None]) + triangle_edges_x.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 0], + polygon_vertex_array[triangle_v1_global_idx + 0], + polygon_vertex_array[triangle_v2_global_idx + 0], + polygon_vertex_array[triangle_v0_global_idx + 0], + None, + ] + ) + triangle_edges_y.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 1], + polygon_vertex_array[triangle_v1_global_idx + 1], + polygon_vertex_array[triangle_v2_global_idx + 1], + polygon_vertex_array[triangle_v0_global_idx + 1], + None, + ] + ) + triangle_edges_z.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 2], + polygon_vertex_array[triangle_v1_global_idx + 2], + polygon_vertex_array[triangle_v2_global_idx + 2], + polygon_vertex_array[triangle_v0_global_idx + 2], + None, + ] + ) # Move to next polygon polygon_v0_idx += vertex_count @@ -118,7 +168,7 @@ polygon_edges_y = [] polygon_edges_z = [] polygon_global_start_index = 0 -coordinate_step = 3 # step per vertex +coordinate_step = 3 # step per vertex for vertex_count in vertices_per_polygon: # Must have at least a triangle if vertex_count < 3: @@ -143,18 +193,19 @@ polygon_global_start_index += vertex_count * coordinate_step - # Create mesh -mesh_3D = go.Mesh3d(x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color='rgba(244,22,100,0.6)') +mesh_3D = go.Mesh3d( + x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color="rgba(244,22,100,0.6)" +) # Create edge lines for triangles triangle_edges_3d = go.Scatter3d( x=triangle_edges_x, y=triangle_edges_y, z=triangle_edges_z, - mode='lines', - name='', - line=dict(color= 'rgb(0,0,0)', width=1) + mode="lines", + name="", + line=dict(color="rgb(0,0,0)", width=1), ) # Create outer edge lines for polygon @@ -162,16 +213,16 @@ x=polygon_edges_x, y=polygon_edges_y, z=polygon_edges_z, - mode='lines', - name='', - line=dict(color= 'rgb(0,0,0)', width=1) + mode="lines", + name="", + line=dict(color="rgb(0,0,0)", width=1), ) fig = go.Figure( data=[ mesh_3D, # triangle_edges_3d, - polygon_edges_3d + polygon_edges_3d, ] ) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py index da05c5ee47..4b5563916a 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py @@ -35,9 +35,9 @@ y_array = [] z_array = [] for i in range(0, len(vertex_array), num_vertex_coords): - x_array.append(vertex_array[i + 0] ) - y_array.append(vertex_array[i + 1] ) - z_array.append(vertex_array[i + 2] ) + x_array.append(vertex_array[i + 0]) + y_array.append(vertex_array[i + 1]) + z_array.append(vertex_array[i + 2]) # Create triangular mesh i_array = [] @@ -50,16 +50,16 @@ k_array.extend([i + 2]) mesh_3d = go.Mesh3d( - x=x_array, - y=y_array, - z=z_array, - i=i_array, - j=j_array, - k=k_array, - intensity=np.linspace(-5, 5, 1000, endpoint=True), - showscale=True, - colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], - ) + x=x_array, + y=y_array, + z=z_array, + i=i_array, + j=j_array, + k=k_array, + intensity=np.linspace(-5, 5, 1000, endpoint=True), + showscale=True, + colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], +) # Create edges between points in triangles Xe = [] @@ -67,25 +67,21 @@ Ze = [] step_per_triangle = num_vertex_coords * num_vertices_per_triangle for i in range(0, len(vertex_array), step_per_triangle): - Xe.extend([vertex_array[i + 0], vertex_array[i + 3], vertex_array[i + 6], None]) # x-coordinates of start and end points of the edge - Ye.extend([vertex_array[i + 1], vertex_array[i + 4], vertex_array[i + 7], None]) # y-coordinates of start and end points of the edge - Ze.extend([vertex_array[i + 2], vertex_array[i + 5], vertex_array[i + 8], None]) # z-coordinates of start and end points of the edge + Xe.extend( + [vertex_array[i + 0], vertex_array[i + 3], vertex_array[i + 6], None] + ) # x-coordinates of start and end points of the edge + Ye.extend( + [vertex_array[i + 1], vertex_array[i + 4], vertex_array[i + 7], None] + ) # y-coordinates of start and end points of the edge + Ze.extend( + [vertex_array[i + 2], vertex_array[i + 5], vertex_array[i + 8], None] + ) # z-coordinates of start and end points of the edge edges_3d = go.Scatter3d( - x=Xe, - y=Ye, - z=Ze, - mode='lines', - name='', - line=dict(color= 'rgb(70,70,70)', width=1) + x=Xe, y=Ye, z=Ze, mode="lines", name="", line=dict(color="rgb(70,70,70)", width=1) ) -fig = go.Figure( - data=[ - mesh_3d, - edges_3d - ] -) +fig = go.Figure(data=[mesh_3d, edges_3d]) print(f"j array: {j_array}") print(f"Number of vertices: {len(vertex_array) / 3}") From 548d74720ef0586a8823af05124d6d340e28b87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 6 Mar 2024 08:02:40 +0100 Subject: [PATCH 19/45] Adjust according to build warnings/errors --- .../RivPolylineIntersectionGeometryGenerator.cpp | 6 ++---- .../RivPolylineIntersectionGeometryGenerator.h | 3 +++ ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp | 2 -- GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp | 2 -- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index 48e2ef0b96..6c4d0b9194 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -28,8 +28,6 @@ #include "cvfPlane.h" #include "cvfVertexWelder.h" -#pragma optimize( "", off ) - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -81,10 +79,10 @@ const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::triangleVxes() //-------------------------------------------------------------------------------------------------- const std::vector& RivPolylineIntersectionGeometryGenerator::triangleVxToCellCornerInterpolationWeights() const { + // Not implemented - not in use CVF_ASSERT( false ); - // Not implemented error - return {}; + return m_emptyTriVxToCellCornerWeights; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index a1d63b47ee..d32d651e01 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -82,4 +82,7 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI std::vector m_polygonToCellIdxMap; cvf::ref m_polygonVertices; std::vector m_verticesPerPolygon; + + // Dummy vectors for GeomGen Interface + const std::vector m_emptyTriVxToCellCornerWeights = {}; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp index 23c3a30e83..80a74c8e9e 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseView.cpp @@ -128,8 +128,6 @@ #include -#pragma optimize( "", off ) - CAF_PDM_XML_SOURCE_INIT( RimEclipseView, "ReservoirView" ); //-------------------------------------------------------------------------------------------------- /// diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index eb29fe5154..4d5d3f477c 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -55,8 +55,6 @@ #include "qfileinfo.h" #include "qstring.h" -#pragma optimize( "", off ) - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- From 8f50da0212829db769ebc52bcd8fe2b58a3a9193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 6 Mar 2024 15:32:23 +0100 Subject: [PATCH 20/45] Backup - WIP --- .../RicPointTangentManipulatorPartMgr.cpp | 12 +- .../RicPointTangentManipulatorPartMgr.h | 2 +- .../RivEnclosingPolygonGenerator.cpp | 31 ++- .../RivEnclosingPolygonGenerator.h | 5 +- ...vPolylineIntersectionGeometryGenerator.cpp | 138 ++++++---- ...RivPolylineIntersectionGeometryGenerator.h | 24 +- .../GrpcProtos/GridGeometryExtraction.proto | 19 +- ..._geometry_extraction_cut_along_polyline.py | 53 +++- ...action_cut_along_polyline_TEST_RESPONSE.py | 247 ++++++++++++++++++ ...on_cut_along_polyline_TRIANGLE_VERTICES.py | 3 +- .../RiaGrpcGridGeometryExtractionService.cpp | 61 +++-- 11 files changed, 482 insertions(+), 113 deletions(-) create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py diff --git a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp index 5ac922ab30..fe21eb2bb7 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp +++ b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp @@ -109,7 +109,7 @@ void RicPointTangentManipulatorPartMgr::originAndTangent( cvf::Vec3d* origin, cv //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::setPolyline( const std::vector& polyline ) { - m_polyline = polyline; + m_polylineUtm = polyline; } //-------------------------------------------------------------------------------------------------- @@ -192,10 +192,10 @@ void RicPointTangentManipulatorPartMgr::updateManipulatorFromRay( const cvf::Ray double closestDistance = std::numeric_limits::max(); cvf::Vec3d closestPoint; - for ( size_t i = 1; i < m_polyline.size(); i++ ) + for ( size_t i = 1; i < m_polylineUtm.size(); i++ ) { - const auto& p1 = m_polyline[i]; - const auto& p2 = m_polyline[i - 1]; + const auto& p1 = m_polylineUtm[i]; + const auto& p2 = m_polylineUtm[i - 1]; double normalizedIntersection; const auto pointOnLine = cvf::GeometryTools::projectPointOnLine( p1, p2, newOrigin, &normalizedIntersection ); @@ -256,7 +256,7 @@ void RicPointTangentManipulatorPartMgr::endManipulator() //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::recreateAllGeometryAndParts() { - if ( m_polyline.empty() ) + if ( m_polylineUtm.empty() ) { createHorizontalPlaneHandle(); createVerticalAxisHandle(); @@ -272,7 +272,7 @@ void RicPointTangentManipulatorPartMgr::recreateAllGeometryAndParts() //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::createGeometryOnly() { - if ( m_polyline.empty() ) + if ( m_polylineUtm.empty() ) { m_handleParts[HandleType::HORIZONTAL_PLANE]->setDrawable( createHorizontalPlaneGeo().p() ); m_handleParts[HandleType::VERTICAL_AXIS]->setDrawable( createVerticalAxisGeo().p() ); diff --git a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h index 67d6917e5f..c77de1b1a2 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h +++ b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h @@ -102,7 +102,7 @@ class RicPointTangentManipulatorPartMgr : public cvf::Object double m_handleSize; bool m_isGeometryUpdateNeeded; - std::vector m_polyline; + std::vector m_polylineUtm; HandleType m_activeHandle; cvf::Vec3d m_initialPickPoint; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp index bd4f9eac1a..caff983b82 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -25,7 +25,7 @@ /// //-------------------------------------------------------------------------------------------------- PolygonVertexWelder::PolygonVertexWelder( double weldEpsilon ) - : m_epsilon( weldEpsilon ) + : m_epsilonSquared( weldEpsilon * weldEpsilon ) , m_first( cvf::UNDEFINED_UINT ) { } @@ -52,14 +52,6 @@ std::vector PolygonVertexWelder::weldVerticesAndGetIndices( const std //-------------------------------------------------------------------------------------------------- cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3f& vertex ) { - // Compute cell coordinates of bounding box of vertex epsilon neighborhood - int left = static_cast( ( vertex.x() - m_epsilon ) ); - int right = static_cast( ( vertex.x() + m_epsilon ) ); - int front = static_cast( ( vertex.y() - m_epsilon ) ); - int back = static_cast( ( vertex.y() + m_epsilon ) ); - int bottom = static_cast( ( vertex.z() - m_epsilon ) ); - int top = static_cast( ( vertex.z() + m_epsilon ) ); - // Call function to step through linked list of bucket, testing // if vertex is within the epsilon of one of the vertices in the bucket cvf::uint indexOfLocatedVertex = locateVertexInPolygon( vertex ); @@ -96,14 +88,12 @@ cvf::ref PolygonVertexWelder::createVertexArray() const //-------------------------------------------------------------------------------------------------- cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3f& vertex ) const { - const auto epsilonSquared = m_epsilon * m_epsilon; - cvf::uint currentIndex = m_first; while ( currentIndex != cvf::UNDEFINED_UINT ) { // Weld point within tolerance float distanceSquared = ( m_vertex[currentIndex] - vertex ).lengthSquared(); - if ( distanceSquared < epsilonSquared ) + if ( distanceSquared < m_epsilonSquared ) { return currentIndex; } @@ -170,7 +160,7 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() // // Must have at least 3 edges to construct a polygon - CVF_ASSERT( m_allEdgeKeys.size() >= 3 ); + CVF_ASSERT( isValidPolygon() ); // Map of edge key and number of occurrences std::map edgeKeysAndCount; @@ -190,13 +180,13 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() } // At least a triangle is needed to construct a polygon - CVF_ASSERT( edgeKeysAndCount.size() >= 3 ); // This occurs to often? + CVF_ASSERT( edgeKeysAndCount.size() >= 3 ); // Extract boundary edge keys from all edge keys and count std::set boundaryEdges; - for ( const auto& [key, value] : edgeKeysAndCount ) + for ( const auto& [key, count] : edgeKeysAndCount ) { - if ( value == 1 ) + if ( count == 1 ) { boundaryEdges.insert( cvf::EdgeKey::fromkeyVal( key ) ); } @@ -220,6 +210,7 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() const int end = currentEdge.index2(); if ( start == cvf::UNDEFINED_UINT || end == cvf::UNDEFINED_UINT ) { + // Throw error? break; } @@ -269,6 +260,14 @@ std::vector RivEnclosingPolygonGenerator::getPolygonVertices() const return m_polygonVertices; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RivEnclosingPolygonGenerator::isValidPolygon() const +{ + return m_allEdgeKeys.size() >= size_t( 3 ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h index e9c362ce8d..f8e7a37b83 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -50,7 +50,7 @@ class PolygonVertexWelder cvf::uint addVertexToPolygon( const cvf::Vec3f& vertex ); private: - const double m_epsilon; // Tolerance for vertex welding, radius around vertex defining welding neighborhood + const double m_epsilonSquared; // Tolerance for vertex welding, radius around vertex defining welding neighborhood cvf::uint m_first; // Start of linked list std::vector m_next; // Links each vertex to next in linked list. Always numVertices long, will grow as vertices are added @@ -72,8 +72,7 @@ class RivEnclosingPolygonGenerator std::vector getPolygonVertices() const; - bool isValidPolygon() const { return m_allEdgeKeys.size() >= size_t( 3 ); } - size_t numEdges() const { return m_allEdgeKeys.size(); } + bool isValidPolygon() const; void addTriangleVertices( const cvf::Vec3f& p0, const cvf::Vec3f& p1, const cvf::Vec3f& p2 ); void constructEnclosingPolygon(); diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index 6c4d0b9194..109a556eca 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -31,12 +31,11 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerator( std::vector& polyline, +RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerator( std::vector& polylineUtm, RivIntersectionHexGridInterface* grid ) - : m_polyline( polyline ) + : m_polylineUtm( polylineUtm ) , m_hexGrid( grid ) { - m_triangleVxes = new cvf::Vec3fArray; m_polygonVertices = new cvf::Vec3fArray; } @@ -53,7 +52,6 @@ RivPolylineIntersectionGeometryGenerator::~RivPolylineIntersectionGeometryGenera bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const { return m_polygonVertices->size() > 0; - // return m_triangleVxes->size() > 0; } //-------------------------------------------------------------------------------------------------- @@ -61,8 +59,10 @@ bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const //-------------------------------------------------------------------------------------------------- const std::vector& RivPolylineIntersectionGeometryGenerator::triangleToCellIndex() const { - CVF_ASSERT( m_triangleVxes->size() > 0 ); - return m_triangleToCellIdxMap; + // Not implemented - not in use + CVF_ASSERT( false ); + + return m_emptyTriangleToCellIdxMap; } //-------------------------------------------------------------------------------------------------- @@ -70,8 +70,10 @@ const std::vector& RivPolylineIntersectionGeometryGenerator::triangleToC //-------------------------------------------------------------------------------------------------- const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::triangleVxes() const { - CVF_ASSERT( m_triangleVxes->size() > 0 ); - return m_triangleVxes.p(); + // Not implemented - not in use + CVF_ASSERT( false ); + + return nullptr; } //-------------------------------------------------------------------------------------------------- @@ -112,6 +114,15 @@ const std::vector& RivPolylineIntersectionGeometryGenerator::polygonToCe return m_polygonToCellIdxMap; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::vector& RivPolylineIntersectionGeometryGenerator::polylineSegmentsMeshData() const +{ + CVF_ASSERT( m_polylineSegmentsMeshData.size() > 0 ); + return m_polylineSegmentsMeshData; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -125,10 +136,10 @@ void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf //-------------------------------------------------------------------------------------------------- void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) { - if ( m_triangleVxes->size() != 0 || m_polygonVertices->size() != 0 || m_hexGrid.isNull() ) return; + if ( m_polygonVertices->size() != 0 || m_hexGrid.isNull() ) return; - std::vector calculatedTriangleVertices; - std::vector calculatedPolygonVertices; + std::vector calculatedPolygonVertices; + std::vector polylineSegmentMeshData = {}; // Mesh data per polyline segment cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); @@ -155,26 +166,43 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const auto zAxisDirection = -cvf::Vec3d::Z_AXIS; // NOTE: Negative or positive direction? const cvf::Vec3d maxHeightVec = zAxisDirection * gridBBox.radius(); - if ( m_polyline.size() > 1 ) + if ( m_polylineUtm.size() > 1 ) { - const size_t numPoints = m_polyline.size(); + const size_t numPoints = m_polylineUtm.size(); size_t pointIdx = 0; + + // Loop over polyline segments + // + // Create intersection geometry for each polyline segment and clip triangles outside the + // polyline segment, using UTM-coordinates. + // + // Afterwards convert to "local" coordinates (p1 as origin), where the local uz-coordinates + // for each vertex is calculated using Pythagoras theorem. + // + // As the plane is parallel to the z-axis, the local uz-coordinates per polyline segment + // can be calculated using Pythagoras theorem. Where a segment is defined between p1 and p2, + // which implies p1 is origin of the local coordinate system uz. + // + // For a segment a UTM coordinate (x_utm,y_utm,z_utm) converts to u = sqrt(x^2 + y^2) and z = z. + // Where x, y and z are local vertex coordinates, after subtracting the (x_utm, y_utm, z_utm)-values + // for p1 from the vertex UTM-coordinates. while ( pointIdx < numPoints - 1 ) { - size_t nextPointIdx = RivSectionFlattener::indexToNextValidPoint( m_polyline, zAxisDirection, pointIdx ); - if ( nextPointIdx == size_t( -1 ) || nextPointIdx >= m_polyline.size() ) + size_t nextPointIdx = RivSectionFlattener::indexToNextValidPoint( m_polylineUtm, zAxisDirection, pointIdx ); + if ( nextPointIdx == size_t( -1 ) || nextPointIdx >= m_polylineUtm.size() ) { break; } - // Start and end point of polyline segment - const cvf::Vec3d p1 = m_polyline[pointIdx]; - const cvf::Vec3d p2 = m_polyline[nextPointIdx]; + // Start and end point of polyline segment in UTM-coordinates + const cvf::Vec3d p1 = m_polylineUtm[pointIdx]; + const cvf::Vec3d p2 = m_polylineUtm[nextPointIdx]; // Get cell candidates for the polyline segment (subset of global cells) std::vector columnCellCandidates = createPolylineSegmentCellCandidates( *m_hexGrid, p1, p2, maxHeightVec, topDepth, bottomDepth ); + // Plane for the polyline segment cvf::Plane plane; plane.setFromPoints( p1, p2, p2 + maxHeightVec ); @@ -192,14 +220,19 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* cvf::Vec3d cellCorners[8]; size_t cornerIndices[8]; + // Mesh data for polyline segment + + std::vector polygonVerticesUz = {}; + std::vector verticesPerPolygon = {}; + const cvf::Vec3f p1_f( p1 ); + // Handle triangles per cell for ( const auto globalCellIdx : columnCellCandidates ) { if ( ( visibleCells != nullptr ) && ( ( *visibleCells )[globalCellIdx] == 0 ) ) continue; if ( !m_hexGrid->useCell( globalCellIdx ) ) continue; - // if ( globalCellIdx != 93996 ) continue; - + // Perform intersection and clipping of triangles using UTM-coordinates hexPlaneCutTriangleVxes.clear(); m_hexGrid->cellCornerVertices( globalCellIdx, cellCorners ); m_hexGrid->cellCornerIndices( globalCellIdx, cornerIndices ); @@ -211,18 +244,6 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* &hexPlaneCutTriangleVxes, &cellFaceForEachTriangleEdge ); - // DEBUG CODE - bool tmp = false; - if ( hexPlaneCutTriangleVxes.size() < 3 ) - { - tmp = true; - } - if ( globalCellIdx == 93996 ) - { - tmp = true; - } - // END DEBUG CODE - // Clip triangles outside the polyline segment using the planes for point p1 and p2 std::vector clippedTriangleVxes; std::vector cellFaceForEachClippedTriangleEdge; @@ -242,7 +263,7 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* // Object to for adding triangle vertices, well vertices and generate polygon vertices RivEnclosingPolygonGenerator enclosingPolygonGenerator; - // Fill triangle vertices vector with clipped triangle vertices + // Add clipped triangle vertices to the polygon generator using local coordinates size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) { @@ -250,20 +271,19 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const size_t vxIdx1 = vxIdx0 + 1; const size_t vxIdx2 = vxIdx0 + 2; - const cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx ); - const cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx ); - const cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx ); - - calculatedTriangleVertices.emplace_back( point0 ); - calculatedTriangleVertices.emplace_back( point1 ); - calculatedTriangleVertices.emplace_back( point2 ); + // Convert points from UTM to "local" coordinates + // NOTE: Do not subtract z-values. The z-values are used for the uz-coordinates + // and not provided as additional UTM info with response + const cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx - p1 ); + const cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx - p1 ); + const cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx - p1 ); // Add triangle to enclosing polygon line handler enclosingPolygonGenerator.addTriangleVertices( point0, point1, point2 ); } - // Must be a triangle - if ( enclosingPolygonGenerator.numEdges() < size_t( 3 ) ) + // Must be a valid polygon to continue + if ( !enclosingPolygonGenerator.isValidPolygon() ) { continue; } @@ -271,24 +291,42 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* // Construct enclosing polygon after adding each triangle enclosingPolygonGenerator.constructEnclosingPolygon(); const auto& vertices = enclosingPolygonGenerator.getPolygonVertices(); - for ( const auto& vertex : enclosingPolygonGenerator.getPolygonVertices() ) + + // Construct local uz-coordinates using Pythagoras theorem + + for ( const auto& vertex : vertices ) { - calculatedPolygonVertices.push_back( vertex ); + // Convert to local uz-coordinates + const auto u = std::sqrt( vertex.x() * vertex.x() + vertex.y() * vertex.y() ); + const auto z = vertex.z(); + polygonVerticesUz.push_back( cvf::Vec2f( u, z ) ); // u = x, z = y + + // Keep old code for debugging purposes + calculatedPolygonVertices.push_back( vertex + p1_f ); } + verticesPerPolygon.push_back( static_cast( vertices.size() ) ); + // Keep old code for debugging purposes m_verticesPerPolygon.push_back( vertices.size() ); m_polygonToCellIdxMap.push_back( globalCellIdx ); - - // TODO: - // - Create polygon - // - Get polygon indices - // - Convert to "local" coordinates for each polyline segment } + + // Construct polyline segment mesh data + PolylineSegmentMeshData polylineSegmentData; + polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); + polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); + polylineSegmentData.vertexArrayUZ.assign( polygonVerticesUz ); + polylineSegmentData.verticesPerPolygon = verticesPerPolygon; + polylineSegmentData.polygonIndices = {}; // TODO: Add indices or remove from struct? + + // Add polyline segment mesh data to list + m_polylineSegmentsMeshData.push_back( polylineSegmentData ); + + // Set next polyline segment start index pointIdx = nextPointIdx; } } - m_triangleVxes->assign( calculatedTriangleVertices ); m_polygonVertices->assign( calculatedPolygonVertices ); } diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index d32d651e01..b13e7b4b8c 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -45,10 +45,22 @@ class ScalarMapper; class DrawableGeo; } // namespace cvf +struct PolylineSegmentMeshData +{ + // Naming things? FenceMeshSection/PolylineMeshSection? + cvf::Vec2fArray vertexArrayUZ; // Consider std::vector instead, as access methods of Vec2f is .x() and .y() + std::vector polygonIndices; // Not needed when vertices/nodes are not shared between polygons? + std::vector verticesPerPolygon; + std::vector polygonToCellIndexMap; + cvf::Vec2d startUtmXY; + cvf::Vec2d endUtmXY; +}; + +// TODO: Remove inheritance from RivIntersectionGeometryGeneratorInterface? As we do not use triangles class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivIntersectionGeometryGeneratorInterface { public: - RivPolylineIntersectionGeometryGenerator( std::vector& polyline, RivIntersectionHexGridInterface* grid ); + RivPolylineIntersectionGeometryGenerator( std::vector& polylineUtm, RivIntersectionHexGridInterface* grid ); ~RivPolylineIntersectionGeometryGenerator() override; void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); @@ -56,6 +68,8 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI const std::vector& vertiesPerPolygon() const; const std::vector& polygonToCellIndex() const; + const std::vector& polylineSegmentsMeshData() const; + // GeomGen Interface bool isAnyGeometryPresent() const override; const std::vector& triangleToCellIndex() const override; @@ -73,16 +87,16 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI private: cvf::ref m_hexGrid; - const std::vector m_polyline; + const std::vector m_polylineUtm; // Output arrays - cvf::ref m_triangleVxes; - std::vector m_triangleToCellIdxMap; - std::vector m_polygonToCellIdxMap; cvf::ref m_polygonVertices; std::vector m_verticesPerPolygon; + std::vector m_polylineSegmentsMeshData; + // Dummy vectors for GeomGen Interface + const std::vector m_emptyTriangleToCellIdxMap = {}; const std::vector m_emptyTriVxToCellCornerWeights = {}; }; diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index a164a8d494..e4339f8f5d 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -61,22 +61,25 @@ message FenceMeshSection { // U-axis defined by vector from start to end, Z is global Z repeated float vertexArrayUZ = 1; - repeated fixed32 polyIndicesArr = 2; + repeated fixed32 polyIndicesArr = 2; // Note: Redundant if no shared nodes? repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long Vec2d startUtmXY = 6; Vec2d endUtmXY = 7; } -//message CutAlongPolylineResponse -//{ - // repeated FenceMeshSection feceMeshSections = 1; - //Vec3i gridDimensions = 2; -//} - -message CutAlongPolylineResponse +message PolylineTestResponse { + // Test response returning all vertices without "local" section coordinates repeated float polygonVertexArray = 1; repeated fixed32 verticesPerPolygonArr = 2; // Number of vertices per polygon, numPolygons long repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per polygon, numPolygons long } + +message CutAlongPolylineResponse +{ + repeated FenceMeshSection feceMeshSections = 1; + PolylineTestResponse polylineTestResponse = 2; + Vec3i gridDimensions = 3; +} + diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index 0dec245101..a262824c5e 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -53,9 +53,56 @@ grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) ) -polygon_vertex_array_org = cut_along_polyline_response.polygonVertexArray -vertices_per_polygon = cut_along_polyline_response.verticesPerPolygonArr -source_cell_indices = cut_along_polyline_response.sourceCellIndicesArr +fence_mesh_sections = cut_along_polyline_response.feceMeshSections +print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") +# for section in fence_mesh_sections: +for section in fence_mesh_sections: + polygon_vertex_array_uz = section.vertexArrayUZ + vertices_per_polygon = section.verticesPerPolygonArr + + start = section.startUtmXY + end = section.endUtmXY + + # Create directional vector from start to end + direction_vector = [end[0] - start[0], end[1] - start[1]] + + # Decompose the polygon vertex array into x, y, z arrays + x_array = [] + y_array = [] + z_array = [] + + # 2 coordinates per vertex (u, v) + for i in range(0, len(polygon_vertex_array_uz), 2): + u = polygon_vertex_array_uz[i] + z = polygon_vertex_array_uz[i + 1] + + # Calculate x, y from u and directional vector, + # where u is the length along the direction vector + x = start[0] + u * direction_vector[0] + y = start[1] + u * direction_vector[1] + + x_array.append(x) + y_array.append(y) + z_array.append(z) + +# ****************************************** +# ****************************************** +# +# TODO: CONTINUE FROM HERE +# +# ****************************************** +# ****************************************** + + +polygon_vertex_array_org = ( + cut_along_polyline_response.polylineTestResponse.polygonVertexArray +) +vertices_per_polygon = ( + cut_along_polyline_response.polylineTestResponse.verticesPerPolygonArr +) +source_cell_indices = ( + cut_along_polyline_response.polylineTestResponse.sourceCellIndicesArr +) x_start = polygon_vertex_array_org[0] y_start = polygon_vertex_array_org[1] diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py new file mode 100644 index 0000000000..add53ee5be --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py @@ -0,0 +1,247 @@ +import numpy as np + +import plotly.graph_objects as go + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +grid_file_name = None +grid_file_name = ( + "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +) + +# Test polylines +mocked_model_fence_poly_line_utm_xy = [ + 11.2631, + 11.9276, + 14.1083, + 18.2929, + 18.3523, + 10.9173, +] +norne_case_fence_poly_line_utm_xy = [ + 456221, + 7.32113e06, + 457150, + 7.32106e06, + 456885, + 7.32176e06, + 457648, + 7.3226e06, + 458805, + 7.32278e06, +] +norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.32176e06] +norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] + + +fence_poly_line_utm_xy = norne_case_single_segment_poly_line_utm_xy + +cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( + gridFilename=grid_file_name, + fencePolylineUtmXY=fence_poly_line_utm_xy, +) +cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( + grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) +) + +polygon_vertex_array_org = ( + cut_along_polyline_response.polylineTestResponse.polygonVertexArray +) +vertices_per_polygon = ( + cut_along_polyline_response.polylineTestResponse.verticesPerPolygonArr +) +source_cell_indices = ( + cut_along_polyline_response.polylineTestResponse.sourceCellIndicesArr +) + +x_start = polygon_vertex_array_org[0] +y_start = polygon_vertex_array_org[1] +z_start = polygon_vertex_array_org[2] + +# Subtract x_start, y_start, z_start from all x, y, z coordinates +polygon_vertex_array = [] +for i in range(0, len(polygon_vertex_array_org), 3): + polygon_vertex_array.extend( + [ + polygon_vertex_array_org[i] - x_start, + polygon_vertex_array_org[i + 1] - y_start, + polygon_vertex_array_org[i + 2] - z_start, + ] + ) + +num_vertex_coords = 3 # [x, y, z] + +# Create x-, y-, and z-arrays +x_array = [] +y_array = [] +z_array = [] +for i in range(0, len(polygon_vertex_array), num_vertex_coords): + # vertex array is provided as a single array of x, y, z coordinates + # i.e. [x1, y1, z1, x2, y2, z2, x3, y3, z3, ... , xn, yn, zn] + x_array.append(polygon_vertex_array[i + 0]) + y_array.append(polygon_vertex_array[i + 1]) + z_array.append(polygon_vertex_array[i + 2]) + +# Create triangular mesh +vertices = np.array(polygon_vertex_array).reshape(-1, 3) + +# Create mesh data +x, y, z = vertices.T +i = [] +j = [] +k = [] + +# Create edges between points in triangles +triangle_edges_x = [] +triangle_edges_y = [] +triangle_edges_z = [] + +# Populate i, j, k based on vertices_per_polygon +# Create triangles from each polygon +# A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] +# A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] + +polygon_v0_idx = 0 # Index of vertex 0 in the polygon +for vertex_count in vertices_per_polygon: + # Must have at least one triangle + if vertex_count < 3: + polygon_v0_idx += vertex_count + continue + + indices = list(range(polygon_v0_idx, polygon_v0_idx + vertex_count)) + + # Build triangles from polygon + num_triangles = vertex_count - 2 + for triangle_index in range(0, num_triangles): + triangle_v0_idx = polygon_v0_idx + triangle_v1_idx = indices[triangle_index + 1] + triangle_v2_idx = indices[triangle_index + 2] + + # Vertex indices for the triangle + i.append(triangle_v0_idx) + j.append(triangle_v1_idx) + k.append(triangle_v2_idx) + + # Create edge between vertices in triangle with x,y,z coordinates, coordinates per vertex is 3 + coordinate_step = 3 # step per vertex + triangle_v0_global_idx = triangle_v0_idx * coordinate_step + triangle_v1_global_idx = triangle_v1_idx * coordinate_step + triangle_v2_global_idx = triangle_v2_idx * coordinate_step + + # Add x,y,z coordinates for the triangle vertices (closing triangle with 'None') + triangle_edges_x.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 0], + polygon_vertex_array[triangle_v1_global_idx + 0], + polygon_vertex_array[triangle_v2_global_idx + 0], + polygon_vertex_array[triangle_v0_global_idx + 0], + None, + ] + ) + triangle_edges_y.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 1], + polygon_vertex_array[triangle_v1_global_idx + 1], + polygon_vertex_array[triangle_v2_global_idx + 1], + polygon_vertex_array[triangle_v0_global_idx + 1], + None, + ] + ) + triangle_edges_z.extend( + [ + polygon_vertex_array[triangle_v0_global_idx + 2], + polygon_vertex_array[triangle_v1_global_idx + 2], + polygon_vertex_array[triangle_v2_global_idx + 2], + polygon_vertex_array[triangle_v0_global_idx + 2], + None, + ] + ) + + # Move to next polygon + polygon_v0_idx += vertex_count + +# Create edges between points in polygons +polygon_edges_x = [] +polygon_edges_y = [] +polygon_edges_z = [] +polygon_global_start_index = 0 +coordinate_step = 3 # step per vertex +for vertex_count in vertices_per_polygon: + # Must have at least a triangle + if vertex_count < 3: + polygon_global_start_index += vertex_count * coordinate_step + continue + + for vertex_idx in range(0, vertex_count): + vertex_global_idx = polygon_global_start_index + vertex_idx * coordinate_step + polygon_edges_x.append(polygon_vertex_array[vertex_global_idx + 0]) + polygon_edges_y.append(polygon_vertex_array[vertex_global_idx + 1]) + polygon_edges_z.append(polygon_vertex_array[vertex_global_idx + 2]) + + # Close the polygon + polygon_edges_x.append(polygon_vertex_array[polygon_global_start_index + 0]) + polygon_edges_y.append(polygon_vertex_array[polygon_global_start_index + 1]) + polygon_edges_z.append(polygon_vertex_array[polygon_global_start_index + 2]) + + polygon_edges_x.append(None) + polygon_edges_y.append(None) + polygon_edges_z.append(None) + + polygon_global_start_index += vertex_count * coordinate_step + + +# Create mesh +mesh_3D = go.Mesh3d( + x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color="rgba(244,22,100,0.6)" +) + +# Create edge lines for triangles +triangle_edges_3d = go.Scatter3d( + x=triangle_edges_x, + y=triangle_edges_y, + z=triangle_edges_z, + mode="lines", + name="", + line=dict(color="rgb(0,0,0)", width=1), +) + +# Create outer edge lines for polygon +polygon_edges_3d = go.Scatter3d( + x=polygon_edges_x, + y=polygon_edges_y, + z=polygon_edges_z, + mode="lines", + name="", + line=dict(color="rgb(0,0,0)", width=1), +) + +fig = go.Figure( + data=[ + mesh_3D, + # triangle_edges_3d, + polygon_edges_3d, + ] +) + +# print(f"j array: {j_array}") +# print(f"Number of vertices: {len(vertex_array) / 3}") +# print(f"Number of traingles: {num_triangles}") +# print(f"Source cell indices array length: {len(source_cell_indices_arr)}") +# print( +# f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" +# ) +# print( +# f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" +# ) +print(fig.data) + +fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py index 4b5563916a..0014c7df50 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py @@ -24,7 +24,8 @@ grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) ) -vertex_array = cut_along_polyline_response.triangleVertexArray +vertex_array = cut_along_polyline_response.polylineTestResponse.triangleVertexArray +cut_along_polyline_response.polylineTestResponse num_vertex_coords = 3 # [x, y, z] num_vertices_per_triangle = 3 # [v1, v2, v3] diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 4d5d3f477c..af27917002 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -220,21 +220,40 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "No intersection geometry present" ); } - // Get results - // const auto& triangleVertices = polylineIntersectionGenerator->triangleVxes(); - // if ( triangleVertices->size() == 0 ) - //{ - // return grpc::Status( grpc::StatusCode::NOT_FOUND, "No triangle vertices found for polyline" ); - //} - - //// Set vertex_array and quadindicesarr response - // for ( int i = 0; i < triangleVertices->size(); ++i ) - //{ - // const auto& vertex = triangleVertices->get( i ); - // response->add_trianglevertexarray( vertex.x() ); - // response->add_trianglevertexarray( vertex.y() ); - // response->add_trianglevertexarray( vertex.z() ); - // } + // Add fence mesh sections + const auto& polylineSegmentsMeshData = polylineIntersectionGenerator->polylineSegmentsMeshData(); + for ( const auto& segment : polylineSegmentsMeshData ) + { + auto* fenceMeshSection = response->add_fecemeshsections(); + + // Set start UTM (x,y) + rips::Vec2d* startUtmXY = new rips::Vec2d; + startUtmXY->set_x( segment.startUtmXY.x() ); + startUtmXY->set_y( segment.startUtmXY.y() ); + fenceMeshSection->set_allocated_startutmxy( startUtmXY ); + + // Set end UTM (x,y) + rips::Vec2d* endUtmXY = new rips::Vec2d; + endUtmXY->set_x( segment.endUtmXY.x() ); + endUtmXY->set_y( segment.endUtmXY.y() ); + fenceMeshSection->set_allocated_endutmxy( endUtmXY ); + + // Fill the vertext array + for ( const auto& vertex : segment.vertexArrayUZ ) + { + fenceMeshSection->add_vertexarrayuz( vertex.x() ); + fenceMeshSection->add_vertexarrayuz( vertex.y() ); + } + + // Fill the source cell indices array + for ( const auto& sourceCellIndex : segment.polygonToCellIndexMap ) + { + fenceMeshSection->add_sourcecellindicesarr( static_cast( sourceCellIndex ) ); + } + } + + // Add test response + rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; // Polygon vertices const auto& polygonVertices = polylineIntersectionGenerator->polygonVxes(); @@ -245,25 +264,27 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve for ( int i = 0; i < polygonVertices->size(); ++i ) { const auto& vertex = polygonVertices->get( i ); - response->add_polygonvertexarray( vertex.x() ); - response->add_polygonvertexarray( vertex.y() ); - response->add_polygonvertexarray( vertex.z() ); + polylineTestResponse->add_polygonvertexarray( vertex.x() ); + polylineTestResponse->add_polygonvertexarray( vertex.y() ); + polylineTestResponse->add_polygonvertexarray( vertex.z() ); } // Vertices per polygon const auto& verticesPerPolygon = polylineIntersectionGenerator->vertiesPerPolygon(); for ( const auto& elm : verticesPerPolygon ) { - response->add_verticesperpolygonarr( static_cast( elm ) ); + polylineTestResponse->add_verticesperpolygonarr( static_cast( elm ) ); } // Polygon to cell indices const auto& polygonCellIndices = polylineIntersectionGenerator->polygonToCellIndex(); for ( const auto& elm : polygonCellIndices ) { - response->add_sourcecellindicesarr( static_cast( elm ) ); + polylineTestResponse->add_sourcecellindicesarr( static_cast( elm ) ); } + response->set_allocated_polylinetestresponse( polylineTestResponse ); + return grpc::Status::OK; } From 6a10b6f3260bbee1ed526e5c410ea00faa0c4b05 Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Thu, 7 Mar 2024 13:05:10 +0100 Subject: [PATCH 21/45] Set hard coded string for mock model, and fix Ubuntu build error --- .../Intersections/RivEnclosingPolygonGenerator.cpp | 6 +++--- .../Intersections/RivEnclosingPolygonGenerator.h | 2 +- GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp index caff983b82..b02af98dc2 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -206,8 +206,8 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() // Find next edge in the boundary, i.e. edge containing the next vertex index to look for currentEdge = findNextEdge( nextVertexIndex, boundaryEdges ); boundaryEdges.erase( currentEdge ); - const int start = currentEdge.index1(); - const int end = currentEdge.index2(); + const auto start = currentEdge.index1(); + const auto end = currentEdge.index2(); if ( start == cvf::UNDEFINED_UINT || end == cvf::UNDEFINED_UINT ) { // Throw error? @@ -238,7 +238,7 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::EdgeKey RivEnclosingPolygonGenerator::findNextEdge( int vertexIndex, const std::set& boundaryEdges ) +cvf::EdgeKey RivEnclosingPolygonGenerator::findNextEdge( cvf::uint vertexIndex, const std::set& boundaryEdges ) { for ( auto& elm : boundaryEdges ) { diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h index f8e7a37b83..9cc6df1eb6 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -78,7 +78,7 @@ class RivEnclosingPolygonGenerator void constructEnclosingPolygon(); private: - static cvf::EdgeKey findNextEdge( int vertextIndex, const std::set& boundaryEdges ); + static cvf::EdgeKey findNextEdge( cvf::uint vertextIndex, const std::set& boundaryEdges ); private: PolygonVertexWelder m_polygonVertexWelder; // Add and weld vertices for a polygon, provides vertex index diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index af27917002..78aad7607d 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -427,7 +427,11 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeApplicationAndEclip if ( filePath.empty() ) { - // For empty grid file name, use mock model + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Empty file path" ); + } + if ( filePath == "MOCKED_TEST_GRID" ) + { + // For testing, use mock model m_application->createMockModel(); } else From 0ed0d81765e14d667418b9a9430e0c8bccfe8639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 8 Mar 2024 15:25:00 +0100 Subject: [PATCH 22/45] Minor cleanup - WIP --- .../RicPointTangentManipulatorPartMgr.cpp | 12 +- .../RicPointTangentManipulatorPartMgr.h | 2 +- .../RivEnclosingPolygonGenerator.cpp | 40 +-- .../RivEnclosingPolygonGenerator.h | 21 +- ...vPolylineIntersectionGeometryGenerator.cpp | 133 ++++---- ...RivPolylineIntersectionGeometryGenerator.h | 40 +-- .../GrpcProtos/GridGeometryExtraction.proto | 4 +- ..._geometry_extraction_cut_along_polyline.py | 301 +++++++----------- ...action_cut_along_polyline_TEST_RESPONSE.py | 4 +- ...on_cut_along_polyline_TRIANGLE_VERTICES.py | 2 +- ...id_geometry_extraction_get_grid_surface.py | 8 +- .../RiaGrpcGridGeometryExtractionService.cpp | 86 ++--- 12 files changed, 275 insertions(+), 378 deletions(-) diff --git a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp index fe21eb2bb7..5ac922ab30 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp +++ b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.cpp @@ -109,7 +109,7 @@ void RicPointTangentManipulatorPartMgr::originAndTangent( cvf::Vec3d* origin, cv //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::setPolyline( const std::vector& polyline ) { - m_polylineUtm = polyline; + m_polyline = polyline; } //-------------------------------------------------------------------------------------------------- @@ -192,10 +192,10 @@ void RicPointTangentManipulatorPartMgr::updateManipulatorFromRay( const cvf::Ray double closestDistance = std::numeric_limits::max(); cvf::Vec3d closestPoint; - for ( size_t i = 1; i < m_polylineUtm.size(); i++ ) + for ( size_t i = 1; i < m_polyline.size(); i++ ) { - const auto& p1 = m_polylineUtm[i]; - const auto& p2 = m_polylineUtm[i - 1]; + const auto& p1 = m_polyline[i]; + const auto& p2 = m_polyline[i - 1]; double normalizedIntersection; const auto pointOnLine = cvf::GeometryTools::projectPointOnLine( p1, p2, newOrigin, &normalizedIntersection ); @@ -256,7 +256,7 @@ void RicPointTangentManipulatorPartMgr::endManipulator() //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::recreateAllGeometryAndParts() { - if ( m_polylineUtm.empty() ) + if ( m_polyline.empty() ) { createHorizontalPlaneHandle(); createVerticalAxisHandle(); @@ -272,7 +272,7 @@ void RicPointTangentManipulatorPartMgr::recreateAllGeometryAndParts() //-------------------------------------------------------------------------------------------------- void RicPointTangentManipulatorPartMgr::createGeometryOnly() { - if ( m_polylineUtm.empty() ) + if ( m_polyline.empty() ) { m_handleParts[HandleType::HORIZONTAL_PLANE]->setDrawable( createHorizontalPlaneGeo().p() ); m_handleParts[HandleType::VERTICAL_AXIS]->setDrawable( createVerticalAxisGeo().p() ); diff --git a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h index c77de1b1a2..67d6917e5f 100644 --- a/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h +++ b/ApplicationLibCode/Commands/WellPathCommands/PointTangentManipulator/RicPointTangentManipulatorPartMgr.h @@ -102,7 +102,7 @@ class RicPointTangentManipulatorPartMgr : public cvf::Object double m_handleSize; bool m_isGeometryUpdateNeeded; - std::vector m_polylineUtm; + std::vector m_polyline; HandleType m_activeHandle; cvf::Vec3d m_initialPickPoint; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp index b02af98dc2..4e538b3a09 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -40,17 +40,10 @@ void PolygonVertexWelder::reserveVertices( cvf::uint vertexCount ) } //-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector PolygonVertexWelder::weldVerticesAndGetIndices( const std::vector& vertices ) -{ - return {}; -} - +/// Add a vertex to the welder. If the vertex is within the tolerance of an existing vertex, the existing +// vertex index is returned //-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3f& vertex ) +cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3d& vertex ) { // Call function to step through linked list of bucket, testing // if vertex is within the epsilon of one of the vertices in the bucket @@ -69,7 +62,7 @@ cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3f& vertex ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const cvf::Vec3f& PolygonVertexWelder::vertex( cvf::uint index ) const +const cvf::Vec3d& PolygonVertexWelder::vertex( cvf::uint index ) const { return m_vertex[index]; } @@ -77,22 +70,22 @@ const cvf::Vec3f& PolygonVertexWelder::vertex( cvf::uint index ) const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::ref PolygonVertexWelder::createVertexArray() const +cvf::ref PolygonVertexWelder::createVertexArray() const { - cvf::ref vertexArray = new cvf::Vec3fArray( m_vertex ); + cvf::ref vertexArray = new cvf::Vec3dArray( m_vertex ); return vertexArray; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3f& vertex ) const +cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3d& vertex ) const { cvf::uint currentIndex = m_first; while ( currentIndex != cvf::UNDEFINED_UINT ) { // Weld point within tolerance - float distanceSquared = ( m_vertex[currentIndex] - vertex ).lengthSquared(); + const auto distanceSquared = ( m_vertex[currentIndex] - vertex ).lengthSquared(); if ( distanceSquared < m_epsilonSquared ) { return currentIndex; @@ -107,7 +100,7 @@ cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3f& vertex ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::addVertexToPolygon( const cvf::Vec3f& vertex ) +cvf::uint PolygonVertexWelder::addVertexToPolygon( const cvf::Vec3d& vertex ) { // Add vertex and update linked list m_vertex.push_back( vertex ); @@ -131,7 +124,7 @@ cvf::uint PolygonVertexWelder::addVertexToPolygon( const cvf::Vec3f& vertex ) //-------------------------------------------------------------------------------------------------- RivEnclosingPolygonGenerator::RivEnclosingPolygonGenerator() - : m_polygonVertexWelder( 1e-6 ) + : m_polygonVertexWelder( 1e-3 ) { } @@ -169,6 +162,7 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() for ( const auto& edgeKey : m_allEdgeKeys ) { // If edge is already in the set, it occurs more than once and is not a boundary edge + // Assuming no degenerate triangles, i.e. triangle with two or more vertices at the same position if ( edgeKeysAndCount.contains( edgeKey ) ) { edgeKeysAndCount[edgeKey]++; @@ -255,7 +249,7 @@ cvf::EdgeKey RivEnclosingPolygonGenerator::findNextEdge( cvf::uint vertexIndex, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RivEnclosingPolygonGenerator::getPolygonVertices() const +std::vector RivEnclosingPolygonGenerator::getPolygonVertices() const { return m_polygonVertices; } @@ -269,14 +263,22 @@ bool RivEnclosingPolygonGenerator::isValidPolygon() const } //-------------------------------------------------------------------------------------------------- +/// Add triangle vertices to the polygon. The vertices are welded to prevent duplicated vertices /// +/// Assumes that the vertices are given in counter-clockwise order //-------------------------------------------------------------------------------------------------- -void RivEnclosingPolygonGenerator::addTriangleVertices( const cvf::Vec3f& p0, const cvf::Vec3f& p1, const cvf::Vec3f& p2 ) +void RivEnclosingPolygonGenerator::addTriangleVertices( const cvf::Vec3d& p0, const cvf::Vec3d& p1, const cvf::Vec3d& p2 ) { cvf::uint i0 = m_polygonVertexWelder.weldVertexAndGetIndex( p0 ); cvf::uint i1 = m_polygonVertexWelder.weldVertexAndGetIndex( p1 ); cvf::uint i2 = m_polygonVertexWelder.weldVertexAndGetIndex( p2 ); + // Verify three unique vertices - i.e. no degenerate triangle + if ( i0 == i1 || i0 == i2 || i1 == i2 ) + { + return; + } + // Add edges keys to list of all edges m_allEdgeKeys.emplace_back( cvf::EdgeKey( i0, i1 ).toKeyVal() ); m_allEdgeKeys.emplace_back( cvf::EdgeKey( i1, i2 ).toKeyVal() ); diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h index 9cc6df1eb6..3cb7c117a6 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -37,24 +37,21 @@ class PolygonVertexWelder void reserveVertices( cvf::uint vertexCount ); - // Add a vertex to the welder. If the vertex is within the tolerance of an existing vertex, the existing vertex index is returned - // Size of returned index array is equal size of input array - std::vector weldVerticesAndGetIndices( const std::vector& vertices ); // TODO: Remove? - cvf::uint weldVertexAndGetIndex( const cvf::Vec3f& vertex ); + cvf::uint weldVertexAndGetIndex( const cvf::Vec3d& vertex ); - const cvf::Vec3f& vertex( cvf::uint index ) const; - cvf::ref createVertexArray() const; + const cvf::Vec3d& vertex( cvf::uint index ) const; + cvf::ref createVertexArray() const; private: - cvf::uint locateVertexInPolygon( const cvf::Vec3f& vertex ) const; - cvf::uint addVertexToPolygon( const cvf::Vec3f& vertex ); + cvf::uint locateVertexInPolygon( const cvf::Vec3d& vertex ) const; + cvf::uint addVertexToPolygon( const cvf::Vec3d& vertex ); private: const double m_epsilonSquared; // Tolerance for vertex welding, radius around vertex defining welding neighborhood cvf::uint m_first; // Start of linked list std::vector m_next; // Links each vertex to next in linked list. Always numVertices long, will grow as vertices are added - std::vector m_vertex; // Unique vertices within tolerance + std::vector m_vertex; // Unique vertices within tolerance }; /* @@ -70,11 +67,11 @@ class RivEnclosingPolygonGenerator public: RivEnclosingPolygonGenerator(); - std::vector getPolygonVertices() const; + std::vector getPolygonVertices() const; bool isValidPolygon() const; - void addTriangleVertices( const cvf::Vec3f& p0, const cvf::Vec3f& p1, const cvf::Vec3f& p2 ); + void addTriangleVertices( const cvf::Vec3d& p0, const cvf::Vec3d& p1, const cvf::Vec3d& p2 ); void constructEnclosingPolygon(); private: @@ -83,5 +80,5 @@ class RivEnclosingPolygonGenerator private: PolygonVertexWelder m_polygonVertexWelder; // Add and weld vertices for a polygon, provides vertex index std::vector m_allEdgeKeys; // Create edge defined by vertex indices when adding triangle. Using cvf::EdgeKey::toKeyVal() - std::vector m_polygonVertices; // List polygon vertices counter clock-wise + std::vector m_polygonVertices; // List polygon vertices counter clock-wise }; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index 109a556eca..d58283988f 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -31,9 +31,9 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerator( std::vector& polylineUtm, +RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerator( const std::vector& polylineUtmXy, RivIntersectionHexGridInterface* grid ) - : m_polylineUtm( polylineUtm ) + : m_polylineUtm( initializePolylineUtmFromPolylineUtmXy( polylineUtmXy ) ) , m_hexGrid( grid ) { m_polygonVertices = new cvf::Vec3fArray; @@ -49,42 +49,26 @@ RivPolylineIntersectionGeometryGenerator::~RivPolylineIntersectionGeometryGenera //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const -{ - return m_polygonVertices->size() > 0; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivPolylineIntersectionGeometryGenerator::triangleToCellIndex() const -{ - // Not implemented - not in use - CVF_ASSERT( false ); - - return m_emptyTriangleToCellIdxMap; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::triangleVxes() const +std::vector + RivPolylineIntersectionGeometryGenerator::initializePolylineUtmFromPolylineUtmXy( const std::vector& polylineUtmXy ) { - // Not implemented - not in use - CVF_ASSERT( false ); + std::vector polylineUtm; + polylineUtm.reserve( polylineUtmXy.size() ); - return nullptr; + const double zValue = 0.0; + for ( const auto& xy : polylineUtmXy ) + { + polylineUtm.push_back( cvf::Vec3d( xy.x(), xy.y(), zValue ) ); + } + return polylineUtm; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::vector& RivPolylineIntersectionGeometryGenerator::triangleVxToCellCornerInterpolationWeights() const +bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const { - // Not implemented - not in use - CVF_ASSERT( false ); - - return m_emptyTriVxToCellCornerWeights; + return m_polylineSegmentsMeshData.size() > 0; } //-------------------------------------------------------------------------------------------------- @@ -136,36 +120,18 @@ void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf //-------------------------------------------------------------------------------------------------- void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) { - if ( m_polygonVertices->size() != 0 || m_hexGrid.isNull() ) return; - - std::vector calculatedPolygonVertices; - std::vector polylineSegmentMeshData = {}; // Mesh data per polyline segment - - cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); - - const double topDepth = gridBBox.max().z(); - const double bottomDepth = gridBBox.min().z(); - - std::array corners; - gridBBox.cornerVertices( corners.data() ); - - cvf::Vec3d p1_low( corners[0].x(), corners[0].y(), bottomDepth ); - cvf::Vec3d p2_low( corners[1].x(), corners[1].y(), bottomDepth ); - cvf::Vec3d p3_low( corners[2].x(), corners[2].y(), bottomDepth ); - - cvf::Plane lowPlane; - lowPlane.setFromPoints( p1_low, p2_low, p3_low ); + if ( m_hexGrid.isNull() || m_polylineSegmentsMeshData.size() != 0 ) return; - cvf::Vec3d p1_high( p1_low.x(), p1_low.y(), topDepth ); - cvf::Vec3d p2_high( p2_low.x(), p2_low.y(), topDepth ); - cvf::Vec3d p3_high( p3_low.x(), p3_low.y(), topDepth ); - - cvf::Plane highPlane; - highPlane.setFromPoints( p1_high, p2_high, p3_high ); - highPlane.flip(); + // Mesh data per polyline segment + std::vector polylineSegmentMeshData = {}; + std::vector calculatedPolygonVertices = {}; + cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); + const double topDepth = gridBBox.max().z(); + const double bottomDepth = gridBBox.min().z(); const auto zAxisDirection = -cvf::Vec3d::Z_AXIS; // NOTE: Negative or positive direction? const cvf::Vec3d maxHeightVec = zAxisDirection * gridBBox.radius(); + if ( m_polylineUtm.size() > 1 ) { const size_t numPoints = m_polylineUtm.size(); @@ -221,10 +187,8 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* size_t cornerIndices[8]; // Mesh data for polyline segment - - std::vector polygonVerticesUz = {}; - std::vector verticesPerPolygon = {}; - const cvf::Vec3f p1_f( p1 ); + std::vector polygonVerticesUz = {}; + std::vector verticesPerPolygon = {}; // Handle triangles per cell for ( const auto globalCellIdx : columnCellCandidates ) @@ -267,16 +231,19 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) { + // Get triangle vertices const size_t vxIdx0 = triangleIdx * 3; - const size_t vxIdx1 = vxIdx0 + 1; - const size_t vxIdx2 = vxIdx0 + 2; + const auto& vx0 = clippedTriangleVxes[vxIdx0 + 0].vx; + const auto& vx1 = clippedTriangleVxes[vxIdx0 + 1].vx; + const auto& vx2 = clippedTriangleVxes[vxIdx0 + 2].vx; + + // Convert to local coordinates, where p1 is origin. + // The z-values are global z-values in the uz-coordinates. + const cvf::Vec3d point0( vx0.x() - p1.x(), vx0.y() - p1.y(), vx0.z() ); + const cvf::Vec3d point1( vx1.x() - p1.x(), vx1.y() - p1.y(), vx1.z() ); + const cvf::Vec3d point2( vx2.x() - p1.x(), vx2.y() - p1.y(), vx2.z() ); - // Convert points from UTM to "local" coordinates - // NOTE: Do not subtract z-values. The z-values are used for the uz-coordinates - // and not provided as additional UTM info with response - const cvf::Vec3f point0( clippedTriangleVxes[vxIdx0].vx - p1 ); - const cvf::Vec3f point1( clippedTriangleVxes[vxIdx1].vx - p1 ); - const cvf::Vec3f point2( clippedTriangleVxes[vxIdx2].vx - p1 ); + // TODO: Ensure counter clockwise order of vertices point0, point1, point2? // Add triangle to enclosing polygon line handler enclosingPolygonGenerator.addTriangleVertices( point0, point1, point2 ); @@ -293,31 +260,39 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const auto& vertices = enclosingPolygonGenerator.getPolygonVertices(); // Construct local uz-coordinates using Pythagoras theorem - for ( const auto& vertex : vertices ) { - // Convert to local uz-coordinates + // NOTE: Can welding provide drifting of vertex positions? + // TODO: Project (x,y) into plane instead? + // + // Convert to local uz-coordinates, u is the distance along the normalized U-axis const auto u = std::sqrt( vertex.x() * vertex.x() + vertex.y() * vertex.y() ); const auto z = vertex.z(); - polygonVerticesUz.push_back( cvf::Vec2f( u, z ) ); // u = x, z = y + + polygonVerticesUz.push_back( u ); + polygonVerticesUz.push_back( z ); // Keep old code for debugging purposes - calculatedPolygonVertices.push_back( vertex + p1_f ); + calculatedPolygonVertices.push_back( cvf::Vec3f( vertex + p1 ) ); } verticesPerPolygon.push_back( static_cast( vertices.size() ) ); // Keep old code for debugging purposes - m_verticesPerPolygon.push_back( vertices.size() ); - m_polygonToCellIdxMap.push_back( globalCellIdx ); + m_verticesPerPolygon.push_back( vertices.size() ); // TODO: Remove when not needed for debug + m_polygonToCellIdxMap.push_back( globalCellIdx ); // TODO: Remove when not needed for debug } + // Create polygon indices array + std::vector polygonIndices( polygonVerticesUz.size() ); + std::iota( polygonIndices.begin(), polygonIndices.end(), 0 ); + // Construct polyline segment mesh data PolylineSegmentMeshData polylineSegmentData; - polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); - polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); - polylineSegmentData.vertexArrayUZ.assign( polygonVerticesUz ); + polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); + polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); + polylineSegmentData.vertexArrayUZ = polygonVerticesUz; polylineSegmentData.verticesPerPolygon = verticesPerPolygon; - polylineSegmentData.polygonIndices = {}; // TODO: Add indices or remove from struct? + polylineSegmentData.polygonIndices = polygonIndices; // Add polyline segment mesh data to list m_polylineSegmentsMeshData.push_back( polylineSegmentData ); @@ -327,7 +302,7 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* } } - m_polygonVertices->assign( calculatedPolygonVertices ); + m_polygonVertices->assign( calculatedPolygonVertices ); // TODO: Remove when not needed for debug } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index b13e7b4b8c..986696ca43 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -19,14 +19,9 @@ #pragma once -#include "cafPdmPointer.h" - -#include "RivIntersectionGeometryGeneratorInterface.h" - #include "cvfArray.h" #include "cvfBoundingBox.h" -#include "cvfObject.h" #include "cvfVector3.h" #include @@ -47,8 +42,8 @@ class DrawableGeo; struct PolylineSegmentMeshData { - // Naming things? FenceMeshSection/PolylineMeshSection? - cvf::Vec2fArray vertexArrayUZ; // Consider std::vector instead, as access methods of Vec2f is .x() and .y() + // U-axis defined by the unit length vector from start (x,y) to end (x,y), Z is global Z + std::vector vertexArrayUZ; // U coordinate is length along U-axis. Array [u0,z0,u1,z1,...,ui,zi] std::vector polygonIndices; // Not needed when vertices/nodes are not shared between polygons? std::vector verticesPerPolygon; std::vector polygonToCellIndexMap; @@ -56,26 +51,22 @@ struct PolylineSegmentMeshData cvf::Vec2d endUtmXY; }; -// TODO: Remove inheritance from RivIntersectionGeometryGeneratorInterface? As we do not use triangles -class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivIntersectionGeometryGeneratorInterface +class RivPolylineIntersectionGeometryGenerator { public: - RivPolylineIntersectionGeometryGenerator( std::vector& polylineUtm, RivIntersectionHexGridInterface* grid ); - ~RivPolylineIntersectionGeometryGenerator() override; + RivPolylineIntersectionGeometryGenerator( const std::vector& polylineUtmXy, RivIntersectionHexGridInterface* grid ); + ~RivPolylineIntersectionGeometryGenerator(); + + void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); + bool isAnyGeometryPresent() const; - void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); + // TODO: Remove after testing? const cvf::Vec3fArray* polygonVxes() const; const std::vector& vertiesPerPolygon() const; const std::vector& polygonToCellIndex() const; const std::vector& polylineSegmentsMeshData() const; - // GeomGen Interface - bool isAnyGeometryPresent() const override; - const std::vector& triangleToCellIndex() const override; - const std::vector& triangleVxToCellCornerInterpolationWeights() const override; - const cvf::Vec3fArray* triangleVxes() const override; - private: void calculateArrays( cvf::UByteArray* visibleCells ); static std::vector createPolylineSegmentCellCandidates( const RivIntersectionHexGridInterface& hexGrid, @@ -85,18 +76,17 @@ class RivPolylineIntersectionGeometryGenerator : public cvf::Object, public RivI const double topDepth, const double bottomDepth ); + static std::vector initializePolylineUtmFromPolylineUtmXy( const std::vector& polylineUtmXy ); + private: cvf::ref m_hexGrid; const std::vector m_polylineUtm; - // Output arrays + // Output + std::vector m_polylineSegmentsMeshData; + + // TMP Output arrays for debug std::vector m_polygonToCellIdxMap; cvf::ref m_polygonVertices; std::vector m_verticesPerPolygon; - - std::vector m_polylineSegmentsMeshData; - - // Dummy vectors for GeomGen Interface - const std::vector m_emptyTriangleToCellIdxMap = {}; - const std::vector m_emptyTriVxToCellCornerWeights = {}; }; diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index e4339f8f5d..1b03cf9e1e 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -59,8 +59,8 @@ message CutAlongPolylineRequest message FenceMeshSection { - // U-axis defined by vector from start to end, Z is global Z - repeated float vertexArrayUZ = 1; + // U-axis defined by the unit length vector from start to end, Z is global Z + repeated float vertexArrayUZ = 1; // U coordinate is length along U-axis repeated fixed32 polyIndicesArr = 2; // Note: Redundant if no shared nodes? repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index a262824c5e..1f4786ac70 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -13,7 +13,7 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = None +grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" ) @@ -43,7 +43,7 @@ norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] -fence_poly_line_utm_xy = norne_case_single_segment_poly_line_utm_xy +fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( gridFilename=grid_file_name, @@ -55,223 +55,140 @@ fence_mesh_sections = cut_along_polyline_response.feceMeshSections print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") -# for section in fence_mesh_sections: + +section_mesh_3d = [] +section_polygon_edges_3d = [] + +# Use first segment start (x,y) as origin +x_origin = fence_mesh_sections[0].startUtmXY.x if len(fence_mesh_sections) > 0 else 0 +y_origin = fence_mesh_sections[0].startUtmXY.y if len(fence_mesh_sections) > 0 else 0 for section in fence_mesh_sections: + # Continue to next section polygon_vertex_array_uz = section.vertexArrayUZ vertices_per_polygon = section.verticesPerPolygonArr - start = section.startUtmXY - end = section.endUtmXY + # Get start and end coordinates (local coordinates) + start_x = section.startUtmXY.x - x_origin + start_y = section.startUtmXY.y - y_origin + end_x = section.endUtmXY.x - x_origin + end_y = section.endUtmXY.y - y_origin # Create directional vector from start to end - direction_vector = [end[0] - start[0], end[1] - start[1]] + direction_vector = [end_x - start_x, end_y - start_y] + + # Normalize the directional vector + length = np.sqrt(direction_vector[0] ** 2 + direction_vector[1] ** 2) + direction_vector_norm = [direction_vector[0] / length, direction_vector[1] / length] # Decompose the polygon vertex array into x, y, z arrays + # 2 coordinates per vertex (u, v) + vertex_step = 2 + + # Create x-, y-, and z-arrays x_array = [] y_array = [] z_array = [] - - # 2 coordinates per vertex (u, v) - for i in range(0, len(polygon_vertex_array_uz), 2): + for i in range(0, len(polygon_vertex_array_uz), vertex_step): u = polygon_vertex_array_uz[i] z = polygon_vertex_array_uz[i + 1] # Calculate x, y from u and directional vector, # where u is the length along the direction vector - x = start[0] + u * direction_vector[0] - y = start[1] + u * direction_vector[1] + x = start_x + u * direction_vector_norm[0] + y = start_y + u * direction_vector_norm[1] x_array.append(x) y_array.append(y) z_array.append(z) -# ****************************************** -# ****************************************** -# -# TODO: CONTINUE FROM HERE -# -# ****************************************** -# ****************************************** - - -polygon_vertex_array_org = ( - cut_along_polyline_response.polylineTestResponse.polygonVertexArray -) -vertices_per_polygon = ( - cut_along_polyline_response.polylineTestResponse.verticesPerPolygonArr -) -source_cell_indices = ( - cut_along_polyline_response.polylineTestResponse.sourceCellIndicesArr -) + i = [] + j = [] + k = [] + # Populate i, j, k based on vertices_per_polygon + # Create triangles from each polygon + # A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] + # A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] + polygon_v0_idx = 0 # Index of vertex 0 in the polygon + for vertex_count in vertices_per_polygon: + # Must have at least one triangle + if vertex_count < 3: + polygon_v0_idx += vertex_count + continue + + indices = list(range(polygon_v0_idx, polygon_v0_idx + vertex_count)) + + # Build triangles from polygon + num_triangles = vertex_count - 2 + for triangle_index in range(0, num_triangles): + triangle_v0_idx = polygon_v0_idx + triangle_v1_idx = indices[triangle_index + 1] + triangle_v2_idx = indices[triangle_index + 2] + + # Vertex indices for the triangle + i.append(triangle_v0_idx) + j.append(triangle_v1_idx) + k.append(triangle_v2_idx) + + # Move to next polygon + polygon_v0_idx += vertex_count -x_start = polygon_vertex_array_org[0] -y_start = polygon_vertex_array_org[1] -z_start = polygon_vertex_array_org[2] - -# Subtract x_start, y_start, z_start from all x, y, z coordinates -polygon_vertex_array = [] -for i in range(0, len(polygon_vertex_array_org), 3): - polygon_vertex_array.extend( - [ - polygon_vertex_array_org[i] - x_start, - polygon_vertex_array_org[i + 1] - y_start, - polygon_vertex_array_org[i + 2] - z_start, - ] + # Create edges between points in polygons + polygon_edges_x = [] + polygon_edges_y = [] + polygon_edges_z = [] + polygon_start_index = 0 + for vertex_count in vertices_per_polygon: + # Must have at least a triangle + if vertex_count < 3: + polygon_start_index += vertex_count + continue + + for vertex_idx in range(0, vertex_count): + vertex_global_idx = polygon_start_index + vertex_idx + polygon_edges_x.append(x_array[vertex_global_idx]) + polygon_edges_y.append(y_array[vertex_global_idx]) + polygon_edges_z.append(z_array[vertex_global_idx]) + + # Close the polygon + polygon_edges_x.append(x_array[polygon_start_index]) + polygon_edges_y.append(y_array[polygon_start_index]) + polygon_edges_z.append(z_array[polygon_start_index]) + + polygon_edges_x.append(None) + polygon_edges_y.append(None) + polygon_edges_z.append(None) + + polygon_start_index += vertex_count + + # Add section mesh + section_mesh_3d.append( + go.Mesh3d( + x=x_array, + y=y_array, + z=z_array, + i=i, + j=j, + k=k, + opacity=0.8, + color="rgba(244,22,100,0.6)", + ) ) -num_vertex_coords = 3 # [x, y, z] - -# Create x-, y-, and z-arrays -x_array = [] -y_array = [] -z_array = [] -for i in range(0, len(polygon_vertex_array), num_vertex_coords): - # vertex array is provided as a single array of x, y, z coordinates - # i.e. [x1, y1, z1, x2, y2, z2, x3, y3, z3, ... , xn, yn, zn] - x_array.append(polygon_vertex_array[i + 0]) - y_array.append(polygon_vertex_array[i + 1]) - z_array.append(polygon_vertex_array[i + 2]) - -# Create triangular mesh -vertices = np.array(polygon_vertex_array).reshape(-1, 3) - -# Create mesh data -x, y, z = vertices.T -i = [] -j = [] -k = [] - -# Create edges between points in triangles -triangle_edges_x = [] -triangle_edges_y = [] -triangle_edges_z = [] - -# Populate i, j, k based on vertices_per_polygon -# Create triangles from each polygon -# A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] -# A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] - -polygon_v0_idx = 0 # Index of vertex 0 in the polygon -for vertex_count in vertices_per_polygon: - # Must have at least one triangle - if vertex_count < 3: - polygon_v0_idx += vertex_count - continue - - indices = list(range(polygon_v0_idx, polygon_v0_idx + vertex_count)) - - # Build triangles from polygon - num_triangles = vertex_count - 2 - for triangle_index in range(0, num_triangles): - triangle_v0_idx = polygon_v0_idx - triangle_v1_idx = indices[triangle_index + 1] - triangle_v2_idx = indices[triangle_index + 2] - - # Vertex indices for the triangle - i.append(triangle_v0_idx) - j.append(triangle_v1_idx) - k.append(triangle_v2_idx) - - # Create edge between vertices in triangle with x,y,z coordinates, coordinates per vertex is 3 - coordinate_step = 3 # step per vertex - triangle_v0_global_idx = triangle_v0_idx * coordinate_step - triangle_v1_global_idx = triangle_v1_idx * coordinate_step - triangle_v2_global_idx = triangle_v2_idx * coordinate_step - - # Add x,y,z coordinates for the triangle vertices (closing triangle with 'None') - triangle_edges_x.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 0], - polygon_vertex_array[triangle_v1_global_idx + 0], - polygon_vertex_array[triangle_v2_global_idx + 0], - polygon_vertex_array[triangle_v0_global_idx + 0], - None, - ] + # Add section polygon edges + section_polygon_edges_3d.append( + go.Scatter3d( + x=polygon_edges_x, + y=polygon_edges_y, + z=polygon_edges_z, + mode="lines", + name="", + line=dict(color="rgb(0,0,0)", width=1), ) - triangle_edges_y.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 1], - polygon_vertex_array[triangle_v1_global_idx + 1], - polygon_vertex_array[triangle_v2_global_idx + 1], - polygon_vertex_array[triangle_v0_global_idx + 1], - None, - ] - ) - triangle_edges_z.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 2], - polygon_vertex_array[triangle_v1_global_idx + 2], - polygon_vertex_array[triangle_v2_global_idx + 2], - polygon_vertex_array[triangle_v0_global_idx + 2], - None, - ] - ) - - # Move to next polygon - polygon_v0_idx += vertex_count - -# Create edges between points in polygons -polygon_edges_x = [] -polygon_edges_y = [] -polygon_edges_z = [] -polygon_global_start_index = 0 -coordinate_step = 3 # step per vertex -for vertex_count in vertices_per_polygon: - # Must have at least a triangle - if vertex_count < 3: - polygon_global_start_index += vertex_count * coordinate_step - continue - - for vertex_idx in range(0, vertex_count): - vertex_global_idx = polygon_global_start_index + vertex_idx * coordinate_step - polygon_edges_x.append(polygon_vertex_array[vertex_global_idx + 0]) - polygon_edges_y.append(polygon_vertex_array[vertex_global_idx + 1]) - polygon_edges_z.append(polygon_vertex_array[vertex_global_idx + 2]) - - # Close the polygon - polygon_edges_x.append(polygon_vertex_array[polygon_global_start_index + 0]) - polygon_edges_y.append(polygon_vertex_array[polygon_global_start_index + 1]) - polygon_edges_z.append(polygon_vertex_array[polygon_global_start_index + 2]) - - polygon_edges_x.append(None) - polygon_edges_y.append(None) - polygon_edges_z.append(None) - - polygon_global_start_index += vertex_count * coordinate_step - - -# Create mesh -mesh_3D = go.Mesh3d( - x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color="rgba(244,22,100,0.6)" -) - -# Create edge lines for triangles -triangle_edges_3d = go.Scatter3d( - x=triangle_edges_x, - y=triangle_edges_y, - z=triangle_edges_z, - mode="lines", - name="", - line=dict(color="rgb(0,0,0)", width=1), -) + ) -# Create outer edge lines for polygon -polygon_edges_3d = go.Scatter3d( - x=polygon_edges_x, - y=polygon_edges_y, - z=polygon_edges_z, - mode="lines", - name="", - line=dict(color="rgb(0,0,0)", width=1), -) +figure_data = section_mesh_3d + section_polygon_edges_3d -fig = go.Figure( - data=[ - mesh_3D, - # triangle_edges_3d, - polygon_edges_3d, - ] -) +fig = go.Figure(data=figure_data) # print(f"j array: {j_array}") # print(f"Number of vertices: {len(vertex_array) / 3}") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py index add53ee5be..69b677f7a3 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py @@ -13,7 +13,7 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = None +grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" ) @@ -43,7 +43,7 @@ norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] -fence_poly_line_utm_xy = norne_case_single_segment_poly_line_utm_xy +fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( gridFilename=grid_file_name, diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py index 0014c7df50..dbe5d4fe1c 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py @@ -13,7 +13,7 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = None +grid_file_name = "MOCKED_TEST_GRID" fence_poly_line_utm_xy = [11.2631, 11.9276, 14.1083, 18.2929, 18.3523, 10.9173] cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index a168b31688..8b07463a3a 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -9,9 +9,13 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = None +grid_file_name = "MOCKED_TEST_GRID" +# grid_file_name = ( +# "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +# ) + ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( - iMin=0, iMax=1, jMin=1, jMax=3, kMin=0, kMax=3 + iMin=0, iMax=1, jMin=1, jMax=3, kMin=3, kMax=3 ) # ijk_index_filter = None diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 78aad7607d..5e82120d18 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -181,14 +181,12 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } // Convert polyline to vector of cvf::Vec3d - std::vector polyline; - const double zValue = 0.0; + std::vector polylineUtmXy; for ( int i = 0; i < fencePolyline.size(); i += 2 ) { const double xValue = fencePolyline.Get( i ); const double yValue = fencePolyline.Get( i + 1 ); - cvf::Vec3d point = cvf::Vec3d( xValue, yValue, zValue ); - polyline.push_back( point ); + polylineUtmXy.push_back( cvf::Vec2d( xValue, yValue ) ); } RigActiveCellInfo* activeCellInfo = nullptr; // No active cell info for grid @@ -196,7 +194,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve RivEclipseIntersectionGrid* eclipseIntersectionGrid = new RivEclipseIntersectionGrid( m_eclipseView->mainGrid(), activeCellInfo, showInactiveCells ); - auto* polylineIntersectionGenerator = new RivPolylineIntersectionGeometryGenerator( polyline, eclipseIntersectionGrid ); + auto* polylineIntersectionGenerator = + new RivPolylineIntersectionGeometryGenerator( polylineUtmXy, eclipseIntersectionGrid ); // Handle cell visibilities const int firstTimeStep = 0; @@ -238,11 +237,22 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve endUtmXY->set_y( segment.endUtmXY.y() ); fenceMeshSection->set_allocated_endutmxy( endUtmXY ); - // Fill the vertext array - for ( const auto& vertex : segment.vertexArrayUZ ) + // Fill the vertext array with coordinates + for ( const auto& coord : segment.vertexArrayUZ ) { - fenceMeshSection->add_vertexarrayuz( vertex.x() ); - fenceMeshSection->add_vertexarrayuz( vertex.y() ); + fenceMeshSection->add_vertexarrayuz( coord ); + } + + // Fill vertices per polygon array + for ( const auto& verticesPerPolygon : segment.verticesPerPolygon ) + { + fenceMeshSection->add_verticesperpolygonarr( static_cast( verticesPerPolygon ) ); + } + + // Fill polygon indices array + for ( const auto& polygonIndex : segment.polygonIndices ) + { + fenceMeshSection->add_polyindicesarr( static_cast( polygonIndex ) ); } // Fill the source cell indices array @@ -252,38 +262,40 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } } - // Add test response - rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; - - // Polygon vertices - const auto& polygonVertices = polylineIntersectionGenerator->polygonVxes(); - if ( polygonVertices->size() == 0 ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); - } - for ( int i = 0; i < polygonVertices->size(); ++i ) + // Add temporary test response { - const auto& vertex = polygonVertices->get( i ); - polylineTestResponse->add_polygonvertexarray( vertex.x() ); - polylineTestResponse->add_polygonvertexarray( vertex.y() ); - polylineTestResponse->add_polygonvertexarray( vertex.z() ); - } + rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; - // Vertices per polygon - const auto& verticesPerPolygon = polylineIntersectionGenerator->vertiesPerPolygon(); - for ( const auto& elm : verticesPerPolygon ) - { - polylineTestResponse->add_verticesperpolygonarr( static_cast( elm ) ); - } + // Polygon vertices + const auto& polygonVertices = polylineIntersectionGenerator->polygonVxes(); + if ( polygonVertices->size() == 0 ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); + } + for ( int i = 0; i < polygonVertices->size(); ++i ) + { + const auto& vertex = polygonVertices->get( i ); + polylineTestResponse->add_polygonvertexarray( vertex.x() ); + polylineTestResponse->add_polygonvertexarray( vertex.y() ); + polylineTestResponse->add_polygonvertexarray( vertex.z() ); + } - // Polygon to cell indices - const auto& polygonCellIndices = polylineIntersectionGenerator->polygonToCellIndex(); - for ( const auto& elm : polygonCellIndices ) - { - polylineTestResponse->add_sourcecellindicesarr( static_cast( elm ) ); - } + // Vertices per polygon + const auto& verticesPerPolygon = polylineIntersectionGenerator->vertiesPerPolygon(); + for ( const auto& elm : verticesPerPolygon ) + { + polylineTestResponse->add_verticesperpolygonarr( static_cast( elm ) ); + } + + // Polygon to cell indices + const auto& polygonCellIndices = polylineIntersectionGenerator->polygonToCellIndex(); + for ( const auto& elm : polygonCellIndices ) + { + polylineTestResponse->add_sourcecellindicesarr( static_cast( elm ) ); + } - response->set_allocated_polylinetestresponse( polylineTestResponse ); + response->set_allocated_polylinetestresponse( polylineTestResponse ); + } return grpc::Status::OK; } From 491b0c3ff003de4ea8032559744c1bbaf1c15eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 11 Mar 2024 09:55:50 +0100 Subject: [PATCH 23/45] Fix typo in proto --- GrpcInterface/GrpcProtos/GridGeometryExtraction.proto | 2 +- .../grid_geometry_extraction_cut_along_polyline.py | 2 +- GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index 1b03cf9e1e..6b795c8d5d 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -78,7 +78,7 @@ message PolylineTestResponse message CutAlongPolylineResponse { - repeated FenceMeshSection feceMeshSections = 1; + repeated FenceMeshSection fenceMeshSections = 1; PolylineTestResponse polylineTestResponse = 2; Vec3i gridDimensions = 3; } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index 1f4786ac70..d072799436 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -53,7 +53,7 @@ grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) ) -fence_mesh_sections = cut_along_polyline_response.feceMeshSections +fence_mesh_sections = cut_along_polyline_response.fenceMeshSections print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") section_mesh_3d = [] diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 5e82120d18..fab3ee834c 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -223,7 +223,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve const auto& polylineSegmentsMeshData = polylineIntersectionGenerator->polylineSegmentsMeshData(); for ( const auto& segment : polylineSegmentsMeshData ) { - auto* fenceMeshSection = response->add_fecemeshsections(); + auto* fenceMeshSection = response->add_fencemeshsections(); // Set start UTM (x,y) rips::Vec2d* startUtmXY = new rips::Vec2d; From 639f9d0ee3c77fe03ef81b7f49d20e1642169fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 11 Mar 2024 14:14:01 +0100 Subject: [PATCH 24/45] Fix memory leakage for GetGridSurface --- ...id_geometry_extraction_get_grid_surface.py | 16 ++++++------ .../RiaGrpcGridGeometryExtractionService.cpp | 25 +++++++++++-------- .../RiaGrpcGridGeometryExtractionService.h | 7 +++++- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 8b07463a3a..873515d1d8 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -9,15 +9,15 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = "MOCKED_TEST_GRID" -# grid_file_name = ( -# "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" -# ) - -ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( - iMin=0, iMax=1, jMin=1, jMax=3, kMin=3, kMax=3 +# grid_file_name = "MOCKED_TEST_GRID" +grid_file_name = ( + "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" ) -# ijk_index_filter = None + +# ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( +# iMin=0, iMax=1, jMin=1, jMax=3, kMin=3, kMax=3 +# ) +ijk_index_filter = None get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( gridFilename=grid_file_name, diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index fab3ee834c..2e1dd92f07 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -55,6 +55,11 @@ #include "qfileinfo.h" #include "qstring.h" +RiaGrpcGridGeometryExtractionService::RiaGrpcGridGeometryExtractionService() + : m_faceVisibilityFilter( nullptr ) +{ +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -86,15 +91,15 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC m_eclipseView->createGridGeometryParts(); // Initialize grid geometry generator - const bool useOpenMP = false; - auto* gridGeometryGenerator = new cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); - status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); + const bool useOpenMP = false; + auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); // cvf::ref? + status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } - auto* gridSurfaceVertices = gridGeometryGenerator->getOrCreateVertices(); + auto* gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); if ( gridSurfaceVertices == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); @@ -121,9 +126,9 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Source cell indices from main grid part manager std::vector sourceCellIndicesArray = std::vector(); - if ( gridGeometryGenerator->quadToCellFaceMapper() != nullptr ) + if ( gridGeometryGenerator.quadToCellFaceMapper() != nullptr ) { - sourceCellIndicesArray = gridGeometryGenerator->quadToCellFaceMapper()->quadToCellIndicesArray(); + sourceCellIndicesArray = gridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray(); } if ( sourceCellIndicesArray.empty() ) { @@ -366,7 +371,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseCa /// //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGeneratorWithEclipseViewCellVisibility( - cvf::StructGridGeometryGenerator* generator ) + cvf::StructGridGeometryGenerator& generator ) { if ( m_eclipseView == nullptr ) { @@ -385,10 +390,10 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat m_eclipseView->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); // Face visibility filter - auto* faceVisibilityFilter = new RigGridCellFaceVisibilityFilter( mainGrid ); + m_faceVisibilityFilter = RigGridCellFaceVisibilityFilter( mainGrid ); - generator->setCellVisibility( cellVisibilities ); - generator->addFaceVisibilityFilter( faceVisibilityFilter ); + generator.setCellVisibility( cellVisibilities ); // Ownership transferred + generator.addFaceVisibilityFilter( &m_faceVisibilityFilter ); return grpc::Status::OK; } diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 12254b1251..88570e6459 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -20,6 +20,7 @@ #include "GridGeometryExtraction.grpc.pb.h" #include "RiaApplication.h" #include "RiaGrpcServiceInterface.h" +#include "RigGridBase.h" #include "RimEclipseCase.h" #include "RimEclipseView.h" #include "RivGridPartMgr.h" @@ -48,6 +49,8 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr public RiaGrpcServiceInterface { public: + RiaGrpcGridGeometryExtractionService(); + grpc::Status GetGridSurface( grpc::ServerContext* context, const rips::GetGridSurfaceRequest* request, rips::GetGridSurfaceResponse* response ) override; @@ -66,9 +69,11 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr grpc::Status applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ); grpc::Status initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( const std::string filePath ); - grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator* generator ); + grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator ); RiaApplication* m_application = nullptr; RimEclipseCase* m_eclipseCase = nullptr; RimEclipseView* m_eclipseView = nullptr; + + RigGridCellFaceVisibilityFilter m_faceVisibilityFilter; }; From f5dbee792fccb25b2ae133642ef97681e3ea440b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 11 Mar 2024 14:34:41 +0100 Subject: [PATCH 25/45] Fix memory leakage for CutAlongPolyline --- ...vPolylineIntersectionGeometryGenerator.cpp | 2 +- ...RivPolylineIntersectionGeometryGenerator.h | 4 +-- .../RiaGrpcGridGeometryExtractionService.cpp | 34 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index d58283988f..e711cd1e6a 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -120,7 +120,7 @@ void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf //-------------------------------------------------------------------------------------------------- void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) { - if ( m_hexGrid.isNull() || m_polylineSegmentsMeshData.size() != 0 ) return; + if ( m_hexGrid == nullptr || m_polylineSegmentsMeshData.size() != 0 ) return; // Mesh data per polyline segment std::vector polylineSegmentMeshData = {}; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index 986696ca43..85ff677f16 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -79,8 +79,8 @@ class RivPolylineIntersectionGeometryGenerator static std::vector initializePolylineUtmFromPolylineUtmXy( const std::vector& polylineUtmXy ); private: - cvf::ref m_hexGrid; - const std::vector m_polylineUtm; + RivIntersectionHexGridInterface* m_hexGrid = nullptr; + const std::vector m_polylineUtm; // Output std::vector m_polylineSegmentsMeshData; diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 2e1dd92f07..169886f682 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -194,38 +194,38 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve polylineUtmXy.push_back( cvf::Vec2d( xValue, yValue ) ); } - RigActiveCellInfo* activeCellInfo = nullptr; // No active cell info for grid - const bool showInactiveCells = true; - RivEclipseIntersectionGrid* eclipseIntersectionGrid = - new RivEclipseIntersectionGrid( m_eclipseView->mainGrid(), activeCellInfo, showInactiveCells ); + RigActiveCellInfo* activeCellInfo = nullptr; // No active cell info for grid + const bool showInactiveCells = true; + auto eclipseIntersectionGrid = + RivEclipseIntersectionGrid( m_eclipseView->mainGrid(), activeCellInfo, showInactiveCells ); - auto* polylineIntersectionGenerator = - new RivPolylineIntersectionGeometryGenerator( polylineUtmXy, eclipseIntersectionGrid ); + auto polylineIntersectionGenerator = + RivPolylineIntersectionGeometryGenerator( polylineUtmXy, &eclipseIntersectionGrid ); // Handle cell visibilities - const int firstTimeStep = 0; - cvf::UByteArray* visibleCells = new cvf::UByteArray( m_eclipseView->mainGrid()->cellCount() ); - m_eclipseView->calculateCurrentTotalCellVisibility( visibleCells, firstTimeStep ); + const int firstTimeStep = 0; + cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseView->mainGrid()->cellCount() ); + m_eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); // Loop to count number of visible cells int numVisibleCells = 0; - for ( size_t i = 0; i < visibleCells->size(); ++i ) + for ( size_t i = 0; i < visibleCells.size(); ++i ) { - if ( ( *visibleCells )[i] != 0 ) + if ( ( visibleCells )[i] != 0 ) { ++numVisibleCells; } } // Generate intersection - polylineIntersectionGenerator->generateIntersectionGeometry( visibleCells ); - if ( !polylineIntersectionGenerator->isAnyGeometryPresent() ) + polylineIntersectionGenerator.generateIntersectionGeometry( &visibleCells ); + if ( !polylineIntersectionGenerator.isAnyGeometryPresent() ) { return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "No intersection geometry present" ); } // Add fence mesh sections - const auto& polylineSegmentsMeshData = polylineIntersectionGenerator->polylineSegmentsMeshData(); + const auto& polylineSegmentsMeshData = polylineIntersectionGenerator.polylineSegmentsMeshData(); for ( const auto& segment : polylineSegmentsMeshData ) { auto* fenceMeshSection = response->add_fencemeshsections(); @@ -272,7 +272,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; // Polygon vertices - const auto& polygonVertices = polylineIntersectionGenerator->polygonVxes(); + const auto& polygonVertices = polylineIntersectionGenerator.polygonVxes(); if ( polygonVertices->size() == 0 ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); @@ -286,14 +286,14 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } // Vertices per polygon - const auto& verticesPerPolygon = polylineIntersectionGenerator->vertiesPerPolygon(); + const auto& verticesPerPolygon = polylineIntersectionGenerator.vertiesPerPolygon(); for ( const auto& elm : verticesPerPolygon ) { polylineTestResponse->add_verticesperpolygonarr( static_cast( elm ) ); } // Polygon to cell indices - const auto& polygonCellIndices = polylineIntersectionGenerator->polygonToCellIndex(); + const auto& polygonCellIndices = polylineIntersectionGenerator.polygonToCellIndex(); for ( const auto& elm : polygonCellIndices ) { polylineTestResponse->add_sourcecellindicesarr( static_cast( elm ) ); From 4520fe1bbc754547e543acf6089a19570c2fdac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Mon, 11 Mar 2024 14:57:59 +0100 Subject: [PATCH 26/45] Fix incorrect segment data - Missing polygonToCellIndexMap - Incorrect polygonIndices --- ...vPolylineIntersectionGeometryGenerator.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index e711cd1e6a..1a661a3488 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -187,8 +187,9 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* size_t cornerIndices[8]; // Mesh data for polyline segment - std::vector polygonVerticesUz = {}; - std::vector verticesPerPolygon = {}; + std::vector polygonVerticesUz = {}; + std::vector verticesPerPolygon = {}; + std::vector polygonToCellIndexMap = {}; // Handle triangles per cell for ( const auto globalCellIdx : columnCellCandidates ) @@ -276,6 +277,7 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* calculatedPolygonVertices.push_back( cvf::Vec3f( vertex + p1 ) ); } verticesPerPolygon.push_back( static_cast( vertices.size() ) ); + polygonToCellIndexMap.push_back( static_cast( globalCellIdx ) ); // Keep old code for debugging purposes m_verticesPerPolygon.push_back( vertices.size() ); // TODO: Remove when not needed for debug @@ -283,16 +285,18 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* } // Create polygon indices array - std::vector polygonIndices( polygonVerticesUz.size() ); + const auto numVertices = static_cast( polygonVerticesUz.size() / 2 ); + std::vector polygonIndices( numVertices ); std::iota( polygonIndices.begin(), polygonIndices.end(), 0 ); // Construct polyline segment mesh data PolylineSegmentMeshData polylineSegmentData; - polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); - polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); - polylineSegmentData.vertexArrayUZ = polygonVerticesUz; - polylineSegmentData.verticesPerPolygon = verticesPerPolygon; - polylineSegmentData.polygonIndices = polygonIndices; + polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); + polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); + polylineSegmentData.vertexArrayUZ = polygonVerticesUz; + polylineSegmentData.verticesPerPolygon = verticesPerPolygon; + polylineSegmentData.polygonIndices = polygonIndices; + polylineSegmentData.polygonToCellIndexMap = polygonToCellIndexMap; // Add polyline segment mesh data to list m_polylineSegmentsMeshData.push_back( polylineSegmentData ); From ae6131e92e71bb30562d55da3f74ad00082203f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 13 Mar 2024 12:47:47 +0100 Subject: [PATCH 27/45] Fix missing fault faces in GetGridSurface() endpoint Adjust name of python files --- .../RivEnclosingPolygonGenerator.h | 2 +- .../ModelVisualization/RivGridPartMgr.cpp | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../ReservoirDataModel/RigGridBase.h | 6 +- ...on_cut_along_polyline_MULTIPLE_REQUESTS.py | 61 +++++++++++++++++++ ...tion_get_grid_surface_MULTIPLE_REQUESTS.py | 37 +++++++++++ .../RiaGrpcGridGeometryExtractionService.cpp | 16 ++--- .../RiaGrpcGridGeometryExtractionService.h | 2 +- 8 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h index 3cb7c117a6..36294db6c5 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -28,7 +28,7 @@ #include /* - * Class for handling welding of vertices in a polygon to prevent duplicated vertex 3D points within a tolerance margin + * Class for handling welding of vertices internally in a polygon to prevent duplicated vertex 3D points within a tolerance margin */ class PolygonVertexWelder { diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp index 935d35d4bc..4e4e156a69 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp @@ -73,7 +73,7 @@ RivGridPartMgr::RivGridPartMgr( RivCellSetEnum cellSetType, RimEclipseCase* ecli : m_surfaceGenerator( grid, RiaRegressionTestRunner::instance()->useOpenMPForGeometryCreation() ) , m_gridIdx( gridIdx ) , m_grid( grid ) - , m_surfaceFaceFilter( grid ) + , m_surfaceFaceFilter( grid, false ) , m_opacityLevel( 1.0f ) , m_defaultColor( cvf::Color3::WHITE ) , m_eclipseCase( eclipseCase ) diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp index ac27d61adb..6454ccfdf9 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp @@ -572,7 +572,7 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible( size_t const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face ); if ( fault ) { - return false; + return m_includeFaultFaces; } // If the neighbour cell is invisible, we need to draw the face diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h index 72af3574a0..98656cc454 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h @@ -128,13 +128,15 @@ class RigGridBase : public cvf::StructGridInterface class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter { public: - explicit RigGridCellFaceVisibilityFilter( const RigGridBase* grid ) + explicit RigGridCellFaceVisibilityFilter( const RigGridBase* const grid, bool includeFaultFaces ) : m_grid( grid ) + , m_includeFaultFaces( includeFaultFaces ) { } bool isFaceVisible( size_t i, size_t j, size_t k, cvf::StructGridInterface::FaceType face, const cvf::UByteArray* cellVisibility ) const override; private: - const RigGridBase* m_grid; + const RigGridBase* const m_grid; + const bool m_includeFaultFaces; }; diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py new file mode 100644 index 0000000000..4818e9d843 --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py @@ -0,0 +1,61 @@ +import time + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +# grid_file_name = "MOCKED_TEST_GRID" +grid_file_name = ( + "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +) + +# Test polylines +mocked_model_fence_poly_line_utm_xy = [ + 11.2631, + 11.9276, + 14.1083, + 18.2929, + 18.3523, + 10.9173, +] +norne_case_fence_poly_line_utm_xy = [ + 456221, + 7.32113e06, + 457150, + 7.32106e06, + 456885, + 7.32176e06, + 457648, + 7.3226e06, + 458805, + 7.32278e06, +] +norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.32176e06] +norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] + + +fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy + +num_calls = 20 +sleep_time_s = 0.5 + +for i in range(num_calls): + print(f"Call {i+1}/{num_calls}") + cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( + gridFilename=grid_file_name, + fencePolylineUtmXY=fence_poly_line_utm_xy, + ) + cut_along_polyline_response: ( + GridGeometryExtraction__pb2.CutAlongPolylineResponse + ) = grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) + + time.sleep(sleep_time_s) + +print("Done!") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py new file mode 100644 index 0000000000..5260ad486c --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py @@ -0,0 +1,37 @@ +import time + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +# grid_file_name = "MOCKED_TEST_GRID" +grid_file_name = ( + "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" +) + +# ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( +# iMin=0, iMax=1, jMin=1, jMax=3, kMin=3, kMax=3 +# ) +ijk_index_filter = None + +num_calls = 30 +sleep_time_s = 0.5 + +for i in range(num_calls): + print(f"Call {i+1}/{num_calls}") + get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( + gridFilename=grid_file_name, + ijkIndexFilter=ijk_index_filter, + cellIndexFilter=None, + propertyFilter=None, + ) + get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = ( + grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) + ) + + time.sleep(sleep_time_s) + +print("Done!") diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 169886f682..d7928ac2dd 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -56,7 +56,6 @@ #include "qstring.h" RiaGrpcGridGeometryExtractionService::RiaGrpcGridGeometryExtractionService() - : m_faceVisibilityFilter( nullptr ) { } @@ -91,9 +90,9 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC m_eclipseView->createGridGeometryParts(); // Initialize grid geometry generator - const bool useOpenMP = false; - auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); // cvf::ref? - status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); + const bool useOpenMP = false; + auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); + status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; @@ -390,10 +389,12 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat m_eclipseView->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); // Face visibility filter - m_faceVisibilityFilter = RigGridCellFaceVisibilityFilter( mainGrid ); + const bool includeFaultFaces = true; + m_faceVisibilityFilter = std::make_unique( + RigGridCellFaceVisibilityFilter( mainGrid, includeFaultFaces ) ); generator.setCellVisibility( cellVisibilities ); // Ownership transferred - generator.addFaceVisibilityFilter( &m_faceVisibilityFilter ); + generator.addFaceVisibilityFilter( m_faceVisibilityFilter.get() ); return grpc::Status::OK; } @@ -407,7 +408,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::loadGridGeometryFromAbsoluteF QFileInfo projectPathInfo( absolutePath ); std::shared_ptr readerSettings; - readerSettings = RifReaderSettings::createGridOnlyReaderSettings(); + readerSettings = RifReaderSettings::createGridOnlyReaderSettings(); + readerSettings->importFaults = true; // TODO: Set true or false? bool createPlot = true; diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 88570e6459..386599c9d2 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -75,5 +75,5 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr RimEclipseCase* m_eclipseCase = nullptr; RimEclipseView* m_eclipseView = nullptr; - RigGridCellFaceVisibilityFilter m_faceVisibilityFilter; + std::unique_ptr m_faceVisibilityFilter = nullptr; }; From 69c38dfb21de79a13328fd36e49ea123f4112eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 14 Mar 2024 11:16:44 +0100 Subject: [PATCH 28/45] Cache opened grid --- .../RiaGrpcGridGeometryExtractionService.cpp | 197 +++++++++++------- .../RiaGrpcGridGeometryExtractionService.h | 9 +- 2 files changed, 128 insertions(+), 78 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index d7928ac2dd..2396561c3b 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -66,20 +66,24 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC const rips::GetGridSurfaceRequest* request, rips::GetGridSurfaceResponse* response ) { - // Reset all pointers - resetInternalPointers(); - // Initialize pointers - grpc::Status status = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); + grpc::Status status = initializeApplicationAndEclipseCaseFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } + auto* eclipseView = dynamic_cast( m_eclipseCase->views().front() ); + if ( eclipseView == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" ); + } + eclipseView->setShowInactiveCells( true ); + // Apply ijk-filtering - assuming 0-indexing from gRPC if ( request->has_ijkindexfilter() ) { - status = applyIJKCellFilterToEclipseCase( request->ijkindexfilter() ); + status = applyIJKCellFilterToEclipseView( request->ijkindexfilter(), eclipseView ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; @@ -87,12 +91,12 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } // Ensure static geometry parts created for grid part manager in view - m_eclipseView->createGridGeometryParts(); + eclipseView->createGridGeometryParts(); // Initialize grid geometry generator const bool useOpenMP = false; - auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseView->mainGrid(), useOpenMP ); - status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator ); + auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseCase->mainGrid(), useOpenMP ); + status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator, eclipseView ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; @@ -117,7 +121,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Origin in utm is the offset rips::Vec3d* modelOffset = new rips::Vec3d; - const auto mainGridModelOffset = m_eclipseView->mainGrid()->displayModelOffset(); + const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset(); modelOffset->set_x( mainGridModelOffset.x() ); modelOffset->set_y( mainGridModelOffset.y() ); modelOffset->set_z( mainGridModelOffset.z() ); @@ -139,21 +143,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } // Set grid dimensions - const auto countI = m_eclipseView->mainGrid()->cellCountI(); - const auto countJ = m_eclipseView->mainGrid()->cellCountJ(); - const auto countK = m_eclipseView->mainGrid()->cellCountK(); + const auto countI = m_eclipseCase->mainGrid()->cellCountI(); + const auto countJ = m_eclipseCase->mainGrid()->cellCountJ(); + const auto countK = m_eclipseCase->mainGrid()->cellCountK(); rips::Vec3i* dimensions = new rips::Vec3i; dimensions->set_i( countI ); dimensions->set_j( countJ ); dimensions->set_k( countK ); response->set_allocated_griddimensions( dimensions ); - // Close project and return - if ( m_application != nullptr ) - { - m_application->closeProject(); - } - resetInternalPointers(); + // Clear existing view + tearDownExistingViewsInEclipseCase(); + eclipseView = nullptr; + delete eclipseView; return grpc::Status::OK; } @@ -165,18 +167,21 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve const rips::CutAlongPolylineRequest* request, rips::CutAlongPolylineResponse* response ) { - // Reset all pointers - resetInternalPointers(); - // Initialize pointers - grpc::Status status = initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( request->gridfilename() ); + grpc::Status status = initializeApplicationAndEclipseCaseFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } - // Ensure static geometry parts created for grid part manager in view - m_eclipseView->createGridGeometryParts(); + // Get eclipse view, show inactive cells and ensure static geometry parts created for grid part manager in view + auto* eclipseView = dynamic_cast( m_eclipseCase->views().front() ); + if ( eclipseView == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" ); + } + eclipseView->setShowInactiveCells( true ); + eclipseView->createGridGeometryParts(); auto& fencePolyline = request->fencepolylineutmxy(); if ( fencePolyline.size() < 2 ) @@ -196,15 +201,15 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve RigActiveCellInfo* activeCellInfo = nullptr; // No active cell info for grid const bool showInactiveCells = true; auto eclipseIntersectionGrid = - RivEclipseIntersectionGrid( m_eclipseView->mainGrid(), activeCellInfo, showInactiveCells ); + RivEclipseIntersectionGrid( m_eclipseCase->mainGrid(), activeCellInfo, showInactiveCells ); auto polylineIntersectionGenerator = RivPolylineIntersectionGeometryGenerator( polylineUtmXy, &eclipseIntersectionGrid ); // Handle cell visibilities const int firstTimeStep = 0; - cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseView->mainGrid()->cellCount() ); - m_eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); + cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseCase->mainGrid()->cellCount() ); + eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); // Loop to count number of visible cells int numVisibleCells = 0; @@ -301,6 +306,11 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve response->set_allocated_polylinetestresponse( polylineTestResponse ); } + // Clear existing view + tearDownExistingViewsInEclipseCase(); + eclipseView = nullptr; + delete eclipseView; + return grpc::Status::OK; } @@ -319,6 +329,25 @@ std::vector RiaGrpcGridGeometryExtractionService::cre &Self::RequestCutAlongPolyline ) }; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiaGrpcGridGeometryExtractionService::tearDownExistingViewsInEclipseCase() +{ + if ( m_eclipseCase == nullptr ) + { + return; + } + + std::vector eclipseViews = m_eclipseCase->reservoirViews.childrenByType(); + for ( const auto& view : eclipseViews ) + { + m_eclipseCase->reservoirViews.removeChild( view ); + delete view; + } + m_eclipseCase->updateAllRequiredEditors(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -326,34 +355,37 @@ void RiaGrpcGridGeometryExtractionService::resetInternalPointers() { m_application = nullptr; m_eclipseCase = nullptr; - m_eclipseView = nullptr; } //-------------------------------------------------------------------------------------------------- /// Apply ijk-filtering - assuming 0-indexing from gRPC //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ) +grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseView( const rips::IJKIndexFilter& filter, + RimEclipseView* view ) { - if ( m_eclipseCase == nullptr ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse case found" ); - } - if ( m_eclipseView == nullptr ) + if ( view == nullptr ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse view found" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "Uninitialized eclipse view provided" ); } // Find the selected Cell Filter Collection - RimCellFilterCollection* filtColl = m_eclipseView->cellFilterCollection(); + RimCellFilterCollection* filtColl = view->cellFilterCollection(); if ( filtColl == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No cell filter collection found for eclipse view" ); } + // Clear potentially existing filter + const auto existingFilters = filtColl->filters(); + for ( const auto& filter : existingFilters ) + { + filtColl->removeFilter( filter ); + } + // Add range filter object - const int sliceDirection = -1; - const int gridIndex = 0; - RimCellRangeFilter* cellRangeFilter = filtColl->addNewCellRangeFilter( m_eclipseCase, gridIndex, sliceDirection ); + const int sliceDirection = -1; + const int gridIndex = 0; + RimCellRangeFilter* cellRangeFilter = filtColl->addNewCellRangeFilter( view->eclipseCase(), gridIndex, sliceDirection ); // Apply ijk-filter values to range filter object cellRangeFilter->startIndexI = filter.imin() + 1; // Eclipse indexing, first index is 1 @@ -370,11 +402,12 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseCa /// //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGeneratorWithEclipseViewCellVisibility( - cvf::StructGridGeometryGenerator& generator ) + cvf::StructGridGeometryGenerator& generator, + RimEclipseView* view ) { - if ( m_eclipseView == nullptr ) + if ( view == nullptr ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No initialized eclipse view found" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "Uninitialized eclipse view provided" ); } auto* mainGrid = m_eclipseCase->mainGrid(); @@ -386,7 +419,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat // Cell visibilities const int firstTimeStep = 0; auto* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() ); - m_eclipseView->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); + view->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); // Face visibility filter const bool includeFaultFaces = true; @@ -430,55 +463,71 @@ grpc::Status RiaGrpcGridGeometryExtractionService::loadGridGeometryFromAbsoluteF //-------------------------------------------------------------------------------------------------- /// Helper function to get application instance and load eclipse case from given file path //-------------------------------------------------------------------------------------------------- -grpc::Status RiaGrpcGridGeometryExtractionService::initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( - const std::string filePath ) +grpc::Status + RiaGrpcGridGeometryExtractionService::initializeApplicationAndEclipseCaseFromAbsoluteFilePath( const std::string filePath ) { + if ( filePath.empty() ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Empty file path" ); + } + // Get ResInsight instance and open grid m_application = RiaApplication::instance(); - if ( m_application == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "ResInsight instance not found" ); } - // Ensure existing project is closed - m_application->closeProject(); - - if ( filePath.empty() ) + // Open new grid if file name is different from file name of existing case + if ( m_eclipseCase == nullptr || m_eclipseCase->gridFileName() != QString::fromStdString( filePath ) ) { - return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Empty file path" ); - } - if ( filePath == "MOCKED_TEST_GRID" ) - { - // For testing, use mock model - m_application->createMockModel(); - } - else - { - // Load case from file name - auto status = loadGridGeometryFromAbsoluteFilePath( filePath ); - if ( status.error_code() != grpc::StatusCode::OK ) return status; + // Close potential existing projects + m_application->closeProject(); + + if ( filePath == "MOCKED_TEST_GRID" ) + { + // For testing, use mock model + m_application->createMockModel(); + } + else + { + // Load case from file name + auto status = loadGridGeometryFromAbsoluteFilePath( filePath ); + if ( status.error_code() != grpc::StatusCode::OK ) return status; + } + + RimProject* project = m_application->project(); + if ( project == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No project found" ); + } + + auto eclipseCases = project->eclipseCases(); + if ( eclipseCases.empty() || eclipseCases.front() == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse case found for project" ); + } + if ( eclipseCases.size() > 1 ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one grid case found for project" ); + } + m_eclipseCase = eclipseCases.front(); } - RimProject* project = m_application->project(); - if ( project == nullptr ) + if ( m_eclipseCase == nullptr ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No project found" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse case found" ); } - auto eclipseCases = project->eclipseCases(); - if ( eclipseCases.empty() || eclipseCases.front() == nullptr ) + // Ensure one reservoir view for case + if ( m_eclipseCase->views().size() > 1 ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse case found for project" ); + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one view found for eclipse case" ); } - m_eclipseCase = eclipseCases.front(); - - if ( m_eclipseCase->views().empty() || m_eclipseCase->views().front() == nullptr ) + if ( m_eclipseCase->views().empty() ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found for eclipse case" ); + m_eclipseCase->createAndAddReservoirView(); } - m_eclipseView = dynamic_cast( m_eclipseCase->views().front() ); - m_eclipseView->setShowInactiveCells( true ); return grpc::Status::OK; } diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 386599c9d2..20ce4f3ce5 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -64,16 +64,17 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr private: void resetInternalPointers(); + void tearDownExistingViewsInEclipseCase(); grpc::Status loadGridGeometryFromAbsoluteFilePath( const std::string filePath ); - grpc::Status applyIJKCellFilterToEclipseCase( const rips::IJKIndexFilter& filter ); - grpc::Status initializeApplicationAndEclipseCaseAndEclipseViewFromAbsoluteFilePath( const std::string filePath ); + grpc::Status applyIJKCellFilterToEclipseView( const rips::IJKIndexFilter& filter, RimEclipseView* view ); + grpc::Status initializeApplicationAndEclipseCaseFromAbsoluteFilePath( const std::string filePath ); - grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator ); + grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator, + RimEclipseView* view ); RiaApplication* m_application = nullptr; RimEclipseCase* m_eclipseCase = nullptr; - RimEclipseView* m_eclipseView = nullptr; std::unique_ptr m_faceVisibilityFilter = nullptr; }; From 9169ee2e438221e36784505fbbd87ca7fe88bcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 14 Mar 2024 11:32:46 +0100 Subject: [PATCH 29/45] Remove unused code --- .../RiaGrpcGridGeometryExtractionService.cpp | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 2396561c3b..243217fd06 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -174,6 +174,13 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve return status; } + // Validate requested polyline + auto& fencePolyline = request->fencepolylineutmxy(); + if ( fencePolyline.size() < 2 ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Invalid fence polyline - require two or more points" ); + } + // Get eclipse view, show inactive cells and ensure static geometry parts created for grid part manager in view auto* eclipseView = dynamic_cast( m_eclipseCase->views().front() ); if ( eclipseView == nullptr ) @@ -183,12 +190,6 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve eclipseView->setShowInactiveCells( true ); eclipseView->createGridGeometryParts(); - auto& fencePolyline = request->fencepolylineutmxy(); - if ( fencePolyline.size() < 2 ) - { - return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Invalid fence polyline" ); - } - // Convert polyline to vector of cvf::Vec3d std::vector polylineUtmXy; for ( int i = 0; i < fencePolyline.size(); i += 2 ) @@ -211,16 +212,6 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseCase->mainGrid()->cellCount() ); eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); - // Loop to count number of visible cells - int numVisibleCells = 0; - for ( size_t i = 0; i < visibleCells.size(); ++i ) - { - if ( ( visibleCells )[i] != 0 ) - { - ++numVisibleCells; - } - } - // Generate intersection polylineIntersectionGenerator.generateIntersectionGeometry( &visibleCells ); if ( !polylineIntersectionGenerator.isAnyGeometryPresent() ) From 2207bf47e887f1b79e124bd4f0221a43b2da2242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 15 Mar 2024 09:04:02 +0100 Subject: [PATCH 30/45] Remove logging from `instance.py` --- GrpcInterface/Python/rips/instance.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/GrpcInterface/Python/rips/instance.py b/GrpcInterface/Python/rips/instance.py index 1f6f7b0f70..29a96fd614 100644 --- a/GrpcInterface/Python/rips/instance.py +++ b/GrpcInterface/Python/rips/instance.py @@ -8,7 +8,6 @@ from __future__ import annotations import os import socket -import logging import time import tempfile import signal @@ -216,7 +215,6 @@ def __init__(self, port: int = 50051, launched: bool = False) -> None: Args: port(int): port number """ - logging.basicConfig() self.location: str = "localhost:" + str(port) self.channel = grpc.insecure_channel( From 3156953c805595b092f698927dd609b8ce29859e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 15 Mar 2024 14:25:15 +0100 Subject: [PATCH 31/45] Add std::flush to RiaStdOutLogger::writeMessageToLogger For testing of instant std::cout when running in console mode --- ApplicationLibCode/Application/Tools/RiaLogging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ApplicationLibCode/Application/Tools/RiaLogging.cpp b/ApplicationLibCode/Application/Tools/RiaLogging.cpp index 014dcfc281..ae4cb35c9a 100644 --- a/ApplicationLibCode/Application/Tools/RiaLogging.cpp +++ b/ApplicationLibCode/Application/Tools/RiaLogging.cpp @@ -358,7 +358,7 @@ void RiuMessageLoggerBase::writeMessageWithPrefixToLogger( const char* prefix, c //-------------------------------------------------------------------------------------------------- void RiaStdOutLogger::writeMessageToLogger( const std::string& str ) { - std::cout << str; + std::cout << str << std::flush; } //-------------------------------------------------------------------------------------------------- From 88ef3a6fcac07db869877048c4320cb3e1aa2d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 15 Mar 2024 15:26:34 +0100 Subject: [PATCH 32/45] Add functionality to disable filter per dimension for IJK-filter Use min and max = -1 to disable filter (include all cells in dimension) --- .../RiaGrpcGridGeometryExtractionService.cpp | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 243217fd06..1e97981837 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -378,13 +378,43 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseVi const int gridIndex = 0; RimCellRangeFilter* cellRangeFilter = filtColl->addNewCellRangeFilter( view->eclipseCase(), gridIndex, sliceDirection ); + // Eclipse indexing, first index is 1 + // Dimension filter is disabled if both min and max is -1 for respective dimension. I.e. all cells for + // respective dimension are included in the filter. + const bool isIDimensionFilterDisabled = filter.imin() == -1 && filter.imax() == -1; + int startIndexI = filter.imin() + 1; + int cellCountI = filter.imax() - filter.imin() + 1; + if ( isIDimensionFilterDisabled ) + { + startIndexI = 1; + cellCountI = view->mainGrid()->cellCountI(); + } + + const bool isJDimensionFilterDisabled = filter.jmin() == -1 && filter.jmax() == -1; + int startIndexJ = filter.jmin() + 1; + int cellCountJ = filter.jmax() - filter.jmin() + 1; + if ( isJDimensionFilterDisabled ) + { + startIndexJ = 1; + cellCountJ = view->mainGrid()->cellCountJ(); + } + + const bool isKDimensionFilterDisabled = filter.kmin() == -1 && filter.kmax() == -1; + int startIndexK = filter.kmin() + 1; + int cellCountK = filter.kmax() - filter.kmin() + 1; + if ( isKDimensionFilterDisabled ) + { + startIndexK = 1; + cellCountK = view->mainGrid()->cellCountK(); + } + // Apply ijk-filter values to range filter object - cellRangeFilter->startIndexI = filter.imin() + 1; // Eclipse indexing, first index is 1 - cellRangeFilter->startIndexJ = filter.jmin() + 1; // Eclipse indexing, first index is 1 - cellRangeFilter->startIndexK = filter.kmin() + 1; // Eclipse indexing, first index is 1 - cellRangeFilter->cellCountI = filter.imax() - filter.imin() + 1; - cellRangeFilter->cellCountJ = filter.jmax() - filter.jmin() + 1; - cellRangeFilter->cellCountK = filter.kmax() - filter.kmin() + 1; + cellRangeFilter->startIndexI = startIndexI; + cellRangeFilter->startIndexJ = startIndexJ; + cellRangeFilter->startIndexK = startIndexK; + cellRangeFilter->cellCountI = cellCountI; + cellRangeFilter->cellCountJ = cellCountJ; + cellRangeFilter->cellCountK = cellCountK; return grpc::Status::OK; } From c2b41c17b8a48d71667cd26efdd36fee88a6aa99 Mon Sep 17 00:00:00 2001 From: jorgenherje Date: Tue, 19 Mar 2024 09:45:31 +0100 Subject: [PATCH 33/45] Add elapsed time info for responses - Total time - Custom named events with elapsed time (map) ddd --- .../GrpcProtos/GridGeometryExtraction.proto | 10 +- ..._geometry_extraction_cut_along_polyline.py | 11 +- ...on_cut_along_polyline_MULTIPLE_REQUESTS.py | 2 +- ...action_cut_along_polyline_TEST_RESPONSE.py | 2 +- ...id_geometry_extraction_get_grid_surface.py | 33 +++-- ...tion_get_grid_surface_MULTIPLE_REQUESTS.py | 2 +- .../RiaGrpcGridGeometryExtractionService.cpp | 127 +++++++++++++++--- .../RiaGrpcGridGeometryExtractionService.h | 19 ++- 8 files changed, 172 insertions(+), 34 deletions(-) diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index 6b795c8d5d..4b6631b926 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -11,6 +11,12 @@ service GridGeometryExtraction rpc CutAlongPolyline(CutAlongPolylineRequest) returns (CutAlongPolylineResponse); } +message TimeElapsedInfo +{ + fixed32 totalTimeElapsedMs = 1; // Total time elapsed for the entire request + map namedEventsAndTimeElapsedMs = 2; // Time elapsed for each custom named event +} + message IJKIndexFilter { int32 iMin = 1; @@ -49,6 +55,7 @@ message GetGridSurfaceResponse repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long Vec3i gridDimensions = 5; Vec3d originUtm = 6; + TimeElapsedInfo timeElapsedInfo = 7; } message CutAlongPolylineRequest @@ -80,6 +87,7 @@ message CutAlongPolylineResponse { repeated FenceMeshSection fenceMeshSections = 1; PolylineTestResponse polylineTestResponse = 2; - Vec3i gridDimensions = 3; + TimeElapsedInfo timeElapsedInfo = 3; + Vec3i gridDimensions = 4; } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index d072799436..c79d63a5e8 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -15,7 +15,7 @@ grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( - "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) # Test polylines @@ -53,6 +53,11 @@ grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) ) +total_time_elapsed = cut_along_polyline_response.timeElapsedInfo.totalTimeElapsedMs +named_events_and_time_elapsed = ( + cut_along_polyline_response.timeElapsedInfo.namedEventsAndTimeElapsedMs +) + fence_mesh_sections = cut_along_polyline_response.fenceMeshSections print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") @@ -201,5 +206,9 @@ # f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" # ) print(fig.data) +print(f"Total time elapsed: {total_time_elapsed} ms") +# print(f"Time elapsed per event [ms]: {named_events_and_time_elapsed}") +for message, time_elapsed in named_events_and_time_elapsed.items(): + print(f"{message}: {time_elapsed}") fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py index 4818e9d843..0a7398ecbe 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py @@ -13,7 +13,7 @@ # grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( - "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) # Test polylines diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py index 69b677f7a3..84da2874fa 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py @@ -15,7 +15,7 @@ grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( - "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) # Test polylines diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 873515d1d8..01939249ca 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -6,18 +6,22 @@ from rips.generated.GridGeometryExtraction_pb2_grpc import * from rips.generated.GridGeometryExtraction_pb2 import * +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -# grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( - "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) +# grid_file_name = "MOCKED_TEST_GRID" -# ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( -# iMin=0, iMax=1, jMin=1, jMax=3, kMin=3, kMax=3 -# ) -ijk_index_filter = None +ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( + iMin=-1, iMax=-1, jMin=-1, jMax=-1, kMin=-1, kMax=-1 +) +# ijk_index_filter = None get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( gridFilename=grid_file_name, @@ -29,6 +33,11 @@ grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) ) +total_time_elapsed = get_grid_surface_response.timeElapsedInfo.totalTimeElapsedMs +named_events_and_time_elapsed = ( + get_grid_surface_response.timeElapsedInfo.namedEventsAndTimeElapsedMs +) + vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr origin_utm = get_grid_surface_response.originUtm @@ -44,9 +53,9 @@ y_array = [] z_array = [] for i in range(0, len(vertex_array), num_vertex_coords): - x_array.append(vertex_array[i + 0] + origin_utm.x) - y_array.append(vertex_array[i + 1] + origin_utm.y) - z_array.append(vertex_array[i + 2] + origin_utm.z) + x_array.append(vertex_array[i + 0]) + y_array.append(vertex_array[i + 1]) + z_array.append(vertex_array[i + 2]) # Create triangular mesh i_array = [] @@ -75,6 +84,7 @@ ] ) + print(f"Number of quads: {num_quads}") print(f"Source cell indices array length: {len(source_cell_indices_arr)}") print( @@ -85,4 +95,9 @@ ) print(fig.data) +print(f"Total time elapsed: {total_time_elapsed} ms") +# print(f"Time elapsed per event [ms]: {named_events_and_time_elapsed}") +for message, time_elapsed in named_events_and_time_elapsed.items(): + print(f"{message}: {time_elapsed}") + fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py index 5260ad486c..4c8c54092d 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py @@ -9,7 +9,7 @@ # grid_file_name = "MOCKED_TEST_GRID" grid_file_name = ( - "D:\\Git\\resinsight-tutorials\\model-data\\norne\\NORNE_ATW2013_RFTPLT_V2.EGRID" + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) # ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 1e97981837..7e0e9dbdbb 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -55,6 +55,29 @@ #include "qfileinfo.h" #include "qstring.h" +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class ElapsedTimeCount +{ +public: + ElapsedTimeCount(): m_start( std::chrono::high_resolution_clock::now() ){}; + ~ElapsedTimeCount() = default; + + long long elapsedMsCount() const + { + const auto end = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast( end - m_start ); + return elapsed.count(); + } + +private: + const std::chrono::high_resolution_clock::time_point m_start; +}; + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- RiaGrpcGridGeometryExtractionService::RiaGrpcGridGeometryExtractionService() { } @@ -66,6 +89,9 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC const rips::GetGridSurfaceRequest* request, rips::GetGridSurfaceResponse* response ) { + m_elapsedTimeInfo.reset(); + auto totalTimeCount = ElapsedTimeCount(); + // Initialize pointers grpc::Status status = initializeApplicationAndEclipseCaseFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) @@ -90,33 +116,42 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } } - // Ensure static geometry parts created for grid part manager in view + // Configure eclipse view + // - Ensure static geometry parts created for grid part manager in view + // - Initialize grid geometry generator + auto createGridGeometryPartsTimeCount = ElapsedTimeCount(); eclipseView->createGridGeometryParts(); + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridGeometryParts"] = + static_cast( createGridGeometryPartsTimeCount.elapsedMsCount() ); - // Initialize grid geometry generator const bool useOpenMP = false; - auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( m_eclipseCase->mainGrid(), useOpenMP ); + auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP ); status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator, eclipseView ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } - auto* gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); + // Create grid surface vertices + auto createVerticesTimeCount = ElapsedTimeCount(); + auto* gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); if ( gridSurfaceVertices == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); } + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridSurfaceVertices"] = + static_cast( createVerticesTimeCount.elapsedMsCount() ); // Set vertex_array and quadindicesarr response - for ( int i = 0; i < gridSurfaceVertices->size(); ++i ) + auto fillResponseTimeCount = ElapsedTimeCount(); + for ( size_t i = 0; i < gridSurfaceVertices->size(); ++i ) { const auto& vertex = gridSurfaceVertices->get( i ); response->add_vertexarray( vertex.x() ); response->add_vertexarray( vertex.y() ); response->add_vertexarray( vertex.z() ); - response->add_quadindicesarr( i ); + response->add_quadindicesarr( static_cast( i )); } // Origin in utm is the offset @@ -143,20 +178,34 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC } // Set grid dimensions - const auto countI = m_eclipseCase->mainGrid()->cellCountI(); - const auto countJ = m_eclipseCase->mainGrid()->cellCountJ(); - const auto countK = m_eclipseCase->mainGrid()->cellCountK(); rips::Vec3i* dimensions = new rips::Vec3i; - dimensions->set_i( countI ); - dimensions->set_j( countJ ); - dimensions->set_k( countK ); + dimensions->set_i( m_eclipseCase->mainGrid()->cellCountK() ); + dimensions->set_j( m_eclipseCase->mainGrid()->cellCountK() ); + dimensions->set_k( m_eclipseCase->mainGrid()->cellCountK() ); response->set_allocated_griddimensions( dimensions ); + m_elapsedTimeInfo.elapsedTimePerEventMs["FillResponse"] = + static_cast( fillResponseTimeCount.elapsedMsCount() ); + // Clear existing view tearDownExistingViewsInEclipseCase(); eclipseView = nullptr; delete eclipseView; + // Fill elapsed time info + m_elapsedTimeInfo.totalTimeElapsedMs = static_cast( totalTimeCount.elapsedMsCount() ); + + // Add elapsed time info to response + rips::TimeElapsedInfo* elapsedTimeInfo = new rips::TimeElapsedInfo; + elapsedTimeInfo->set_totaltimeelapsedms( m_elapsedTimeInfo.totalTimeElapsedMs ); + for ( const auto& event : m_elapsedTimeInfo.elapsedTimePerEventMs ) + { + const auto& message = event.first; + const auto& timeElapsed = event.second; + ( *elapsedTimeInfo->mutable_namedeventsandtimeelapsedms() )[message] = timeElapsed; + } + response->set_allocated_timeelapsedinfo( elapsedTimeInfo ); + return grpc::Status::OK; } @@ -167,6 +216,9 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve const rips::CutAlongPolylineRequest* request, rips::CutAlongPolylineResponse* response ) { + m_elapsedTimeInfo.reset(); + auto totalTimeCount = ElapsedTimeCount(); + // Initialize pointers grpc::Status status = initializeApplicationAndEclipseCaseFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) @@ -188,7 +240,11 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" ); } eclipseView->setShowInactiveCells( true ); + + auto createGridGeometryPartsTimeCount = ElapsedTimeCount(); eclipseView->createGridGeometryParts(); + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridGeometryParts"] = + static_cast( createGridGeometryPartsTimeCount.elapsedMsCount() ); // Convert polyline to vector of cvf::Vec3d std::vector polylineUtmXy; @@ -213,13 +269,17 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); // Generate intersection + auto generateIntersectionTimeCount = ElapsedTimeCount(); polylineIntersectionGenerator.generateIntersectionGeometry( &visibleCells ); if ( !polylineIntersectionGenerator.isAnyGeometryPresent() ) { return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "No intersection geometry present" ); } + m_elapsedTimeInfo.elapsedTimePerEventMs["GenerateIntersection"] = + static_cast( generateIntersectionTimeCount.elapsedMsCount() ); - // Add fence mesh sections + // Add fence mesh sections to response + auto fillResponseTimeCount = ElapsedTimeCount(); const auto& polylineSegmentsMeshData = polylineIntersectionGenerator.polylineSegmentsMeshData(); for ( const auto& segment : polylineSegmentsMeshData ) { @@ -262,9 +322,20 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } } + // Add grid dimensions + rips::Vec3i* dimensions = new rips::Vec3i; + dimensions->set_i( m_eclipseCase->mainGrid()->cellCountI() ); + dimensions->set_j( m_eclipseCase->mainGrid()->cellCountJ() ); + dimensions->set_k( m_eclipseCase->mainGrid()->cellCountK() ); + response->set_allocated_griddimensions( dimensions ); + + m_elapsedTimeInfo.elapsedTimePerEventMs["FillResponse"] = + static_cast( fillResponseTimeCount.elapsedMsCount() ); + // Add temporary test response { - rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; + auto fillTestResponseTimeCount = ElapsedTimeCount(); + rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; // Polygon vertices const auto& polygonVertices = polylineIntersectionGenerator.polygonVxes(); @@ -272,7 +343,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); } - for ( int i = 0; i < polygonVertices->size(); ++i ) + for ( size_t i = 0; i < polygonVertices->size(); ++i ) { const auto& vertex = polygonVertices->get( i ); polylineTestResponse->add_polygonvertexarray( vertex.x() ); @@ -295,6 +366,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve } response->set_allocated_polylinetestresponse( polylineTestResponse ); + m_elapsedTimeInfo.elapsedTimePerEventMs["FillResponse"] = + static_cast( fillTestResponseTimeCount.elapsedMsCount() ); } // Clear existing view @@ -302,6 +375,20 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve eclipseView = nullptr; delete eclipseView; + // Fill elapsed time info + m_elapsedTimeInfo.totalTimeElapsedMs = static_cast( totalTimeCount.elapsedMsCount() ); + + // Add elapsed time info to response + rips::TimeElapsedInfo* elapsedTimeInfo = new rips::TimeElapsedInfo; + elapsedTimeInfo->set_totaltimeelapsedms( m_elapsedTimeInfo.totalTimeElapsedMs ); + for ( const auto& event : m_elapsedTimeInfo.elapsedTimePerEventMs ) + { + const auto& message = event.first; + const auto& timeElapsed = event.second; + ( *elapsedTimeInfo->mutable_namedeventsandtimeelapsedms() )[message] = timeElapsed; + } + response->set_allocated_timeelapsedinfo( elapsedTimeInfo ); + return grpc::Status::OK; } @@ -431,7 +518,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat return grpc::Status( grpc::StatusCode::NOT_FOUND, "Uninitialized eclipse view provided" ); } - auto* mainGrid = m_eclipseCase->mainGrid(); + auto* mainGrid = view->mainGrid(); if ( mainGrid == nullptr ) { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No main grid found for eclipse view" ); @@ -513,7 +600,10 @@ grpc::Status else { // Load case from file name - auto status = loadGridGeometryFromAbsoluteFilePath( filePath ); + auto loadCaseFromFileNameTimeCount = ElapsedTimeCount(); + auto status = loadGridGeometryFromAbsoluteFilePath( filePath ); + m_elapsedTimeInfo.elapsedTimePerEventMs["LoadGridFromFilePath"] = + static_cast( loadCaseFromFileNameTimeCount.elapsedMsCount() ); if ( status.error_code() != grpc::StatusCode::OK ) return status; } @@ -547,7 +637,10 @@ grpc::Status } if ( m_eclipseCase->views().empty() ) { + auto createAndAddViewTimeCount = ElapsedTimeCount(); m_eclipseCase->createAndAddReservoirView(); + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateAndAddView"] = + static_cast( createAndAddViewTimeCount.elapsedMsCount() ); } return grpc::Status::OK; diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 20ce4f3ce5..04a6dcf8ab 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -73,8 +73,21 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator, RimEclipseView* view ); - RiaApplication* m_application = nullptr; - RimEclipseCase* m_eclipseCase = nullptr; - + RiaApplication* m_application = nullptr; + RimEclipseCase* m_eclipseCase = nullptr; std::unique_ptr m_faceVisibilityFilter = nullptr; + + struct ElapsedTimeInfo + { + std::uint32_t totalTimeElapsedMs = 0; // Total time elapsed for entire request + std::map elapsedTimePerEventMs; // Time elapsed for each custom named event + + void reset() + { + totalTimeElapsedMs = 0; + elapsedTimePerEventMs.clear(); + } + }; + + ElapsedTimeInfo m_elapsedTimeInfo; }; From d7c35fba7c2534b47cce5de7ebdb2cf3ad191e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 20 Mar 2024 13:17:58 +0100 Subject: [PATCH 34/45] Remove generate of grid geometry for intersection endpoint - Prevent creating view and grid geometry parts for interseciton endpoint. Improves runtime. - Set all cells visible directly --- .../RiaGrpcGridGeometryExtractionService.cpp | 71 +++++++++---------- .../RiaGrpcGridGeometryExtractionService.h | 1 + 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 7e0e9dbdbb..51e76506e0 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -61,13 +61,14 @@ class ElapsedTimeCount { public: - ElapsedTimeCount(): m_start( std::chrono::high_resolution_clock::now() ){}; + ElapsedTimeCount() + : m_start( std::chrono::high_resolution_clock::now() ){}; ~ElapsedTimeCount() = default; long long elapsedMsCount() const { const auto end = std::chrono::high_resolution_clock::now(); - auto elapsed = std::chrono::duration_cast( end - m_start ); + auto elapsed = std::chrono::duration_cast( end - m_start ); return elapsed.count(); } @@ -92,13 +93,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC m_elapsedTimeInfo.reset(); auto totalTimeCount = ElapsedTimeCount(); - // Initialize pointers + // Initialize application and eclipse case grpc::Status status = initializeApplicationAndEclipseCaseFromAbsoluteFilePath( request->gridfilename() ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; } + // Ensure view in eclipse case + status = ensureViewInEclipseCase( *m_eclipseCase ); + if ( status.error_code() != grpc::StatusCode::OK ) + { + return status; + } auto* eclipseView = dynamic_cast( m_eclipseCase->views().front() ); if ( eclipseView == nullptr ) { @@ -151,7 +158,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC response->add_vertexarray( vertex.y() ); response->add_vertexarray( vertex.z() ); - response->add_quadindicesarr( static_cast( i )); + response->add_quadindicesarr( static_cast( i ) ); } // Origin in utm is the offset @@ -233,19 +240,6 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "Invalid fence polyline - require two or more points" ); } - // Get eclipse view, show inactive cells and ensure static geometry parts created for grid part manager in view - auto* eclipseView = dynamic_cast( m_eclipseCase->views().front() ); - if ( eclipseView == nullptr ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" ); - } - eclipseView->setShowInactiveCells( true ); - - auto createGridGeometryPartsTimeCount = ElapsedTimeCount(); - eclipseView->createGridGeometryParts(); - m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridGeometryParts"] = - static_cast( createGridGeometryPartsTimeCount.elapsedMsCount() ); - // Convert polyline to vector of cvf::Vec3d std::vector polylineUtmXy; for ( int i = 0; i < fencePolyline.size(); i += 2 ) @@ -263,10 +257,9 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve auto polylineIntersectionGenerator = RivPolylineIntersectionGeometryGenerator( polylineUtmXy, &eclipseIntersectionGrid ); - // Handle cell visibilities - const int firstTimeStep = 0; - cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseCase->mainGrid()->cellCount() ); - eclipseView->calculateCurrentTotalCellVisibility( &visibleCells, firstTimeStep ); + // Use all grid cells for intersection geometry + cvf::UByteArray visibleCells = cvf::UByteArray( m_eclipseCase->mainGrid()->cellCount() ); + visibleCells.setAll( 1 ); // Generate intersection auto generateIntersectionTimeCount = ElapsedTimeCount(); @@ -372,8 +365,6 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve // Clear existing view tearDownExistingViewsInEclipseCase(); - eclipseView = nullptr; - delete eclipseView; // Fill elapsed time info m_elapsedTimeInfo.totalTimeElapsedMs = static_cast( totalTimeCount.elapsedMsCount() ); @@ -426,6 +417,27 @@ void RiaGrpcGridGeometryExtractionService::tearDownExistingViewsInEclipseCase() m_eclipseCase->updateAllRequiredEditors(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +grpc::Status RiaGrpcGridGeometryExtractionService::ensureViewInEclipseCase( RimEclipseCase& eclipseCase ) +{ + // Ensure maximum one reservoir view for case + if ( eclipseCase.views().size() > 1 ) + { + return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one view found for eclipse case" ); + } + + if ( eclipseCase.views().empty() ) + { + auto createAndAddViewTimeCount = ElapsedTimeCount(); + eclipseCase.createAndAddReservoirView(); + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateAndAddView"] = + static_cast( createAndAddViewTimeCount.elapsedMsCount() ); + } + return grpc::Status::OK; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -630,19 +642,6 @@ grpc::Status return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse case found" ); } - // Ensure one reservoir view for case - if ( m_eclipseCase->views().size() > 1 ) - { - return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one view found for eclipse case" ); - } - if ( m_eclipseCase->views().empty() ) - { - auto createAndAddViewTimeCount = ElapsedTimeCount(); - m_eclipseCase->createAndAddReservoirView(); - m_elapsedTimeInfo.elapsedTimePerEventMs["CreateAndAddView"] = - static_cast( createAndAddViewTimeCount.elapsedMsCount() ); - } - return grpc::Status::OK; } diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 04a6dcf8ab..f8372a8d5c 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -66,6 +66,7 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr void resetInternalPointers(); void tearDownExistingViewsInEclipseCase(); + grpc::Status ensureViewInEclipseCase( RimEclipseCase& eclipseCase ); grpc::Status loadGridGeometryFromAbsoluteFilePath( const std::string filePath ); grpc::Status applyIJKCellFilterToEclipseView( const rips::IJKIndexFilter& filter, RimEclipseView* view ); grpc::Status initializeApplicationAndEclipseCaseFromAbsoluteFilePath( const std::string filePath ); From b9589b37191c0f9dcdfb51cb439824c15828ff24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 20 Mar 2024 13:45:24 +0100 Subject: [PATCH 35/45] Have global z in vertexArray for getGridSurface endpoint - originUtm as 3D point changed to originUtmXy as 2D point. - Have global z value for vertex coordinate in vertexArray --- .../GrpcProtos/GridGeometryExtraction.proto | 5 +++-- ...id_geometry_extraction_get_grid_surface.py | 6 ++---- .../RiaGrpcGridGeometryExtractionService.cpp | 20 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index 4b6631b926..ec0f517d9d 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -50,11 +50,12 @@ message GetGridSurfaceRequest message GetGridSurfaceResponse { - repeated float vertexArray = 1; + // Vertex array with local x and y coordinates, around originUtmXy. z is coordinate on global Z + repeated float vertexArray = 1; // [x0, y0, z0, x1, y1, z1, ...] repeated fixed32 quadIndicesArr = 2; // 4*NumQuads long repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per quad, longnumQuads long Vec3i gridDimensions = 5; - Vec3d originUtm = 6; + Vec2d originUtmXy = 6; TimeElapsedInfo timeElapsedInfo = 7; } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 01939249ca..88325929e3 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -40,7 +40,7 @@ vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr -origin_utm = get_grid_surface_response.originUtm +origin_utm_xy = get_grid_surface_response.originUtmXy source_cell_indices_arr = get_grid_surface_response.sourceCellIndicesArr grid_dimensions = get_grid_surface_response.gridDimensions @@ -87,9 +87,7 @@ print(f"Number of quads: {num_quads}") print(f"Source cell indices array length: {len(source_cell_indices_arr)}") -print( - f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" -) +print(f"Origin UTM coordinates [x, y]: [{origin_utm_xy.x}, {origin_utm_xy.y}]") print( f"Grid dimensions [I, J, K]: [{grid_dimensions.i}, {grid_dimensions.j}, {grid_dimensions.k}]" ) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 51e76506e0..a251dcb8d9 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -149,25 +149,27 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridSurfaceVertices"] = static_cast( createVerticesTimeCount.elapsedMsCount() ); + // Retrieve the UTM offset + const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset(); + // Set vertex_array and quadindicesarr response - auto fillResponseTimeCount = ElapsedTimeCount(); + auto fillResponseTimeCount = ElapsedTimeCount(); + const auto zAxisOffset = mainGridModelOffset.z(); for ( size_t i = 0; i < gridSurfaceVertices->size(); ++i ) { const auto& vertex = gridSurfaceVertices->get( i ); response->add_vertexarray( vertex.x() ); response->add_vertexarray( vertex.y() ); - response->add_vertexarray( vertex.z() ); + response->add_vertexarray( vertex.z() + zAxisOffset ); response->add_quadindicesarr( static_cast( i ) ); } - // Origin in utm is the offset - rips::Vec3d* modelOffset = new rips::Vec3d; - const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset(); - modelOffset->set_x( mainGridModelOffset.x() ); - modelOffset->set_y( mainGridModelOffset.y() ); - modelOffset->set_z( mainGridModelOffset.z() ); - response->set_allocated_originutm( modelOffset ); + // Origin is the UTM offset + rips::Vec2d* originUtmXy = new rips::Vec2d; + originUtmXy->set_x( mainGridModelOffset.x() ); + originUtmXy->set_y( mainGridModelOffset.y() ); + response->set_allocated_originutmxy( originUtmXy ); // Source cell indices from main grid part manager std::vector sourceCellIndicesArray = std::vector(); From 9b119e6c0428d61ba4e6d9f434fc047e1eca7f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Wed, 20 Mar 2024 15:02:07 +0100 Subject: [PATCH 36/45] Add read out of OpenMP number of threads Read out of number of threads for OpenMP. Expected to be equal set environment variable OMP_NUM_THREADS --- GrpcInterface/RiaGrpcServer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/GrpcInterface/RiaGrpcServer.cpp b/GrpcInterface/RiaGrpcServer.cpp index 6ca1062d92..1b26eeb94f 100644 --- a/GrpcInterface/RiaGrpcServer.cpp +++ b/GrpcInterface/RiaGrpcServer.cpp @@ -37,6 +37,7 @@ #include #include +#include using grpc::CompletionQueue; using grpc::Server; @@ -141,6 +142,13 @@ void RiaGrpcServerImpl::initialize() ServerBuilder builder; + int numOmpThreads = 0; +#pragma omp parallel + { + numOmpThreads = omp_get_num_threads(); + } + RiaLogging::info( QString( "OpenMP Num Threads: %1" ).arg( numOmpThreads ) ); + // When setting port number to 0, grpc will find and use a valid port number // The port number is assigned to the m_portNumber variable after calling builder.BuildAndStart() QString requestedServerAddress = QString( "localhost:%1" ).arg( m_portNumber ); From f498c79f35c1945fd43bb974e8f3a0a3be180c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 21 Mar 2024 09:15:37 +0100 Subject: [PATCH 37/45] Fix incorrect IJK dimensions in response --- GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index a251dcb8d9..1fdf5c76be 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -188,8 +188,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Set grid dimensions rips::Vec3i* dimensions = new rips::Vec3i; - dimensions->set_i( m_eclipseCase->mainGrid()->cellCountK() ); - dimensions->set_j( m_eclipseCase->mainGrid()->cellCountK() ); + dimensions->set_i( m_eclipseCase->mainGrid()->cellCountI() ); + dimensions->set_j( m_eclipseCase->mainGrid()->cellCountJ() ); dimensions->set_k( m_eclipseCase->mainGrid()->cellCountK() ); response->set_allocated_griddimensions( dimensions ); From 4df9eabf9ca1f4a8f6b524faa3a50ee2854bc598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 21 Mar 2024 11:02:25 +0100 Subject: [PATCH 38/45] Move get number of threads logic to RiaMain --- ApplicationExeCode/RiaMain.cpp | 4 ++++ .../Application/Tools/RiaOpenMPTools.cpp | 19 +++++++++++++++++++ .../Application/Tools/RiaOpenMPTools.h | 1 + GrpcInterface/RiaGrpcServer.cpp | 8 -------- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ApplicationExeCode/RiaMain.cpp b/ApplicationExeCode/RiaMain.cpp index b8d35b48c2..5b490db0b3 100644 --- a/ApplicationExeCode/RiaMain.cpp +++ b/ApplicationExeCode/RiaMain.cpp @@ -18,6 +18,7 @@ #include "RiaArgumentParser.h" #include "RiaMainTools.h" +#include "RiaOpenMPTools.h" #include "RiaPreferences.h" #ifdef ENABLE_GRPC @@ -139,6 +140,9 @@ int main( int argc, char* argv[] ) RiaApplication::ApplicationStatus status = app->handleArguments( &progOpt ); + int numOmpThreads = RiaOpenMPTools::numberOfThreads(); + app->showFormattedTextInMessageBoxOrConsole( QString( "OpenMP Num Threads: %1\n" ).arg( numOmpThreads ) ); + if ( status == RiaApplication::ApplicationStatus::EXIT_COMPLETED ) { // Make sure project is closed to avoid assert and crash in destruction of widgets diff --git a/ApplicationLibCode/Application/Tools/RiaOpenMPTools.cpp b/ApplicationLibCode/Application/Tools/RiaOpenMPTools.cpp index 3f634e975a..f5297ae9d6 100644 --- a/ApplicationLibCode/Application/Tools/RiaOpenMPTools.cpp +++ b/ApplicationLibCode/Application/Tools/RiaOpenMPTools.cpp @@ -48,3 +48,22 @@ int RiaOpenMPTools::currentThreadIndex() return myThread; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int RiaOpenMPTools::numberOfThreads() +{ + int numberOfThreads = 1; + +#ifdef USE_OPENMP + +#pragma omp parallel + { + numberOfThreads = omp_get_num_threads(); + } + +#endif + + return numberOfThreads; +} diff --git a/ApplicationLibCode/Application/Tools/RiaOpenMPTools.h b/ApplicationLibCode/Application/Tools/RiaOpenMPTools.h index cbfc576a64..127507d3d0 100644 --- a/ApplicationLibCode/Application/Tools/RiaOpenMPTools.h +++ b/ApplicationLibCode/Application/Tools/RiaOpenMPTools.h @@ -27,4 +27,5 @@ namespace RiaOpenMPTools { int availableThreadCount(); int currentThreadIndex(); +int numberOfThreads(); }; // namespace RiaOpenMPTools diff --git a/GrpcInterface/RiaGrpcServer.cpp b/GrpcInterface/RiaGrpcServer.cpp index 1b26eeb94f..6ca1062d92 100644 --- a/GrpcInterface/RiaGrpcServer.cpp +++ b/GrpcInterface/RiaGrpcServer.cpp @@ -37,7 +37,6 @@ #include #include -#include using grpc::CompletionQueue; using grpc::Server; @@ -142,13 +141,6 @@ void RiaGrpcServerImpl::initialize() ServerBuilder builder; - int numOmpThreads = 0; -#pragma omp parallel - { - numOmpThreads = omp_get_num_threads(); - } - RiaLogging::info( QString( "OpenMP Num Threads: %1" ).arg( numOmpThreads ) ); - // When setting port number to 0, grpc will find and use a valid port number // The port number is assigned to the m_portNumber variable after calling builder.BuildAndStart() QString requestedServerAddress = QString( "localhost:%1" ).arg( m_portNumber ); From 985e2e21eedb214bbbf8446ce1f7a325937116c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 22 Mar 2024 15:37:30 +0100 Subject: [PATCH 39/45] Split generation of surface vertices and fault vertices for getGirdSurface --- .../ModelVisualization/RivGridPartMgr.cpp | 2 +- .../ReservoirDataModel/RigGridBase.cpp | 2 +- .../ReservoirDataModel/RigGridBase.h | 4 +- GrpcInterface/CMakeLists.txt | 2 + ..._geometry_extraction_cut_along_polyline.py | 3 +- ...on_cut_along_polyline_MULTIPLE_REQUESTS.py | 6 +- ...traction_get_grid_surface POLYGON_COUNT.py | 62 +++++++++++++ ...id_geometry_extraction_get_grid_surface.py | 5 +- .../RiaGrpcGridGeometryExtractionService.cpp | 92 ++++++++++++++++--- .../RiaGrpcGridGeometryExtractionService.h | 14 ++- ...rpcGridGeometryExtractionServiceHelper.cpp | 91 ++++++++++++++++++ ...aGrpcGridGeometryExtractionServiceHelper.h | 38 ++++++++ 12 files changed, 291 insertions(+), 30 deletions(-) create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py create mode 100644 GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.cpp create mode 100644 GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.h diff --git a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp index 4e4e156a69..935d35d4bc 100644 --- a/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp +++ b/ApplicationLibCode/ModelVisualization/RivGridPartMgr.cpp @@ -73,7 +73,7 @@ RivGridPartMgr::RivGridPartMgr( RivCellSetEnum cellSetType, RimEclipseCase* ecli : m_surfaceGenerator( grid, RiaRegressionTestRunner::instance()->useOpenMPForGeometryCreation() ) , m_gridIdx( gridIdx ) , m_grid( grid ) - , m_surfaceFaceFilter( grid, false ) + , m_surfaceFaceFilter( grid ) , m_opacityLevel( 1.0f ) , m_defaultColor( cvf::Color3::WHITE ) , m_eclipseCase( eclipseCase ) diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp index 6454ccfdf9..ac27d61adb 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.cpp @@ -572,7 +572,7 @@ bool RigGridCellFaceVisibilityFilter::isFaceVisible( size_t const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face ); if ( fault ) { - return m_includeFaultFaces; + return false; } // If the neighbour cell is invisible, we need to draw the face diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h index 98656cc454..0f9fc3f1c9 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridBase.h +++ b/ApplicationLibCode/ReservoirDataModel/RigGridBase.h @@ -128,9 +128,8 @@ class RigGridBase : public cvf::StructGridInterface class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter { public: - explicit RigGridCellFaceVisibilityFilter( const RigGridBase* const grid, bool includeFaultFaces ) + explicit RigGridCellFaceVisibilityFilter( const RigGridBase* const grid ) : m_grid( grid ) - , m_includeFaultFaces( includeFaultFaces ) { } @@ -138,5 +137,4 @@ class RigGridCellFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter private: const RigGridBase* const m_grid; - const bool m_includeFaultFaces; }; diff --git a/GrpcInterface/CMakeLists.txt b/GrpcInterface/CMakeLists.txt index 152122dffb..316a6db2fd 100644 --- a/GrpcInterface/CMakeLists.txt +++ b/GrpcInterface/CMakeLists.txt @@ -50,6 +50,7 @@ set(SOURCE_GROUP_HEADER_FILES RiaGrpcPdmObjectService.h RiaGrpcApplicationInterface.h RiaGrpcGridGeometryExtractionService.h + RiaGrpcGridGeometryExtractionServiceHelper.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -67,6 +68,7 @@ set(SOURCE_GROUP_SOURCE_FILES RiaGrpcPdmObjectService.cpp RiaGrpcApplicationInterface.cpp RiaGrpcGridGeometryExtractionService.cpp + RiaGrpcGridGeometryExtractionServiceHelper.cpp ) # Find Protobuf installation Looks for protobuf-config.cmake file installed by diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index c79d63a5e8..72469193a1 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -43,7 +43,8 @@ norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] -fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy +# fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy +fence_poly_line_utm_xy = norne_case_single_segment_poly_line_gap_utm_xy cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( gridFilename=grid_file_name, diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py index 0a7398ecbe..c83078bb9a 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py @@ -43,7 +43,7 @@ fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy -num_calls = 20 +num_calls = 1000 sleep_time_s = 0.5 for i in range(num_calls): @@ -56,6 +56,8 @@ GridGeometryExtraction__pb2.CutAlongPolylineResponse ) = grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) - time.sleep(sleep_time_s) + # fence_mesh_sections = cut_along_polyline_response.fenceMeshSections + # print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") + # time.sleep(sleep_time_s) print("Done!") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py new file mode 100644 index 0000000000..910fd95d3d --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py @@ -0,0 +1,62 @@ +import numpy as np + +import plotly.graph_objects as go + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +grid_file_name = ( + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" +) +# grid_file_name = "MOCKED_TEST_GRID" +# grid_file_name = "D:/ResInsight/GRID__SNORRE_BASECASEGRID.roff" + +ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( + iMin=-1, iMax=-1, jMin=-1, jMax=-1, kMin=1, kMax=12 +) +ijk_index_filter = None + +get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( + gridFilename=grid_file_name, + ijkIndexFilter=ijk_index_filter, + cellIndexFilter=None, + propertyFilter=None, +) +get_grid_surface_response: GridGeometryExtraction__pb2.GetGridSurfaceResponse = ( + grid_geometry_extraction_stub.GetGridSurface(get_grid_surface_request) +) + +total_time_elapsed = get_grid_surface_response.timeElapsedInfo.totalTimeElapsedMs +named_events_and_time_elapsed = ( + get_grid_surface_response.timeElapsedInfo.namedEventsAndTimeElapsedMs +) + +vertex_array = get_grid_surface_response.vertexArray +quad_indices_array = get_grid_surface_response.quadIndicesArr +origin_utm_xy = get_grid_surface_response.originUtmXy +source_cell_indices_arr = get_grid_surface_response.sourceCellIndicesArr +grid_dimensions = get_grid_surface_response.gridDimensions + +num_vertex_coords = 3 # [x, y, z] +num_vertices_per_quad = 4 # [v1, v2, v3, v4] +num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad) + + +print(f"Number of quads: {num_quads}") +print(f"Source cell indices array length: {len(source_cell_indices_arr)}") +print(f"Origin UTM coordinates [x, y]: [{origin_utm_xy.x}, {origin_utm_xy.y}]") +print( + f"Grid dimensions [I, J, K]: [{grid_dimensions.i}, {grid_dimensions.j}, {grid_dimensions.k}]" +) +print(f"Total time elapsed: {total_time_elapsed} ms") +# print(f"Time elapsed per event [ms]: {named_events_and_time_elapsed}") +for message, time_elapsed in named_events_and_time_elapsed.items(): + print(f"{message}: {time_elapsed}") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 88325929e3..7e9e442269 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -17,11 +17,12 @@ "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) # grid_file_name = "MOCKED_TEST_GRID" +# grid_file_name = "D:/ResInsight/GRID__SNORRE_BASECASEGRID.roff" ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( - iMin=-1, iMax=-1, jMin=-1, jMax=-1, kMin=-1, kMax=-1 + iMin=15, iMax=30, jMin=30, jMax=90, kMin=1, kMax=12 ) -# ijk_index_filter = None +ijk_index_filter = None get_grid_surface_request = GridGeometryExtraction__pb2.GetGridSurfaceRequest( gridFilename=grid_file_name, diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 1fdf5c76be..fc5912daec 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -32,11 +32,13 @@ #include "RigGeoMechCaseData.h" #include "RigGridBase.h" #include "RigMainGrid.h" +#include "RigNNCData.h" #include "RimCase.h" #include "RimCellFilterCollection.h" #include "RimCellRangeFilter.h" #include "RimEclipseCase.h" #include "RimEclipseView.h" +#include "RimFaultInViewCollection.h" #include "RimGeoMechCase.h" #include "RimGridView.h" #include "RimProject.h" @@ -112,6 +114,7 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC return grpc::Status( grpc::StatusCode::NOT_FOUND, "No eclipse view found" ); } eclipseView->setShowInactiveCells( true ); + eclipseView->faultCollection()->setActive( false ); // TODO: Check if this is correct?? // Apply ijk-filtering - assuming 0-indexing from gRPC if ( request->has_ijkindexfilter() ) @@ -125,15 +128,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Configure eclipse view // - Ensure static geometry parts created for grid part manager in view - // - Initialize grid geometry generator + // - To include inactive cells and activate requested filter for view auto createGridGeometryPartsTimeCount = ElapsedTimeCount(); eclipseView->createGridGeometryParts(); m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridGeometryParts"] = static_cast( createGridGeometryPartsTimeCount.elapsedMsCount() ); - const bool useOpenMP = false; - auto gridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP ); - status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( gridGeometryGenerator, eclipseView ); + // Set visibility + const bool useOpenMP = false; + auto surfaceGridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP ); + auto faultGridGeometryGenerator = cvf::StructGridGeometryGenerator( eclipseView->mainGrid(), useOpenMP ); + status = initializeGridGeometryGeneratorWithEclipseViewCellVisibility( surfaceGridGeometryGenerator, + faultGridGeometryGenerator, + eclipseView ); if ( status.error_code() != grpc::StatusCode::OK ) { return status; @@ -141,14 +148,24 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Create grid surface vertices auto createVerticesTimeCount = ElapsedTimeCount(); - auto* gridSurfaceVertices = gridGeometryGenerator.getOrCreateVertices(); + auto* gridSurfaceVertices = surfaceGridGeometryGenerator.getOrCreateVertices(); if ( gridSurfaceVertices == nullptr ) { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid vertices found" ); + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid surface vertices found" ); } m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridSurfaceVertices"] = static_cast( createVerticesTimeCount.elapsedMsCount() ); + // Create grid fault vertices + auto createFaultVerticesTimeCount = ElapsedTimeCount(); + auto* gridFaultVertices = faultGridGeometryGenerator.getOrCreateVertices(); + if ( gridFaultVertices == nullptr ) + { + return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid fault vertices found" ); + } + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridFaultVertices"] = + static_cast( createFaultVerticesTimeCount.elapsedMsCount() ); + // Retrieve the UTM offset const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset(); @@ -165,6 +182,18 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC response->add_quadindicesarr( static_cast( i ) ); } + const auto indexOffset = gridSurfaceVertices->size(); + for ( size_t i = 0; i < gridFaultVertices->size(); ++i ) + { + const auto& vertex = gridFaultVertices->get( i ); + response->add_vertexarray( vertex.x() ); + response->add_vertexarray( vertex.y() ); + response->add_vertexarray( vertex.z() + zAxisOffset ); + + auto index = indexOffset + i; + response->add_quadindicesarr( static_cast( index ) ); + } + // Origin is the UTM offset rips::Vec2d* originUtmXy = new rips::Vec2d; originUtmXy->set_x( mainGridModelOffset.x() ); @@ -173,9 +202,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Source cell indices from main grid part manager std::vector sourceCellIndicesArray = std::vector(); - if ( gridGeometryGenerator.quadToCellFaceMapper() != nullptr ) + if ( surfaceGridGeometryGenerator.quadToCellFaceMapper() != nullptr ) { - sourceCellIndicesArray = gridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray(); + for ( const auto& elm : surfaceGridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray() ) + { + sourceCellIndicesArray.push_back( elm ); + } + } + if ( faultGridGeometryGenerator.quadToCellFaceMapper() != nullptr ) + { + for ( const auto& elm : faultGridGeometryGenerator.quadToCellFaceMapper()->quadToCellIndicesArray() ) + { + sourceCellIndicesArray.push_back( elm ); + } } if ( sourceCellIndicesArray.empty() ) { @@ -524,7 +563,8 @@ grpc::Status RiaGrpcGridGeometryExtractionService::applyIJKCellFilterToEclipseVi /// //-------------------------------------------------------------------------------------------------- grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGeneratorWithEclipseViewCellVisibility( - cvf::StructGridGeometryGenerator& generator, + cvf::StructGridGeometryGenerator& surfaceGeometryGenerator, + cvf::StructGridGeometryGenerator& faultGeometryGenerator, RimEclipseView* view ) { if ( view == nullptr ) @@ -541,15 +581,19 @@ grpc::Status RiaGrpcGridGeometryExtractionService::initializeGridGeometryGenerat // Cell visibilities const int firstTimeStep = 0; auto* cellVisibilities = new cvf::UByteArray( mainGrid->cellCount() ); - view->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); + view->calculateCurrentTotalCellVisibility( cellVisibilities, firstTimeStep ); // TODO: Check if this is correct way + // to get cell visibilities // Face visibility filter - const bool includeFaultFaces = true; - m_faceVisibilityFilter = std::make_unique( - RigGridCellFaceVisibilityFilter( mainGrid, includeFaultFaces ) ); + m_surfaceFaceVisibilityFilter = + std::make_unique( RigGridCellFaceVisibilityFilter( mainGrid ) ); + surfaceGeometryGenerator.setCellVisibility( cellVisibilities ); // Ownership transferred + surfaceGeometryGenerator.addFaceVisibilityFilter( m_surfaceFaceVisibilityFilter.get() ); - generator.setCellVisibility( cellVisibilities ); // Ownership transferred - generator.addFaceVisibilityFilter( m_faceVisibilityFilter.get() ); + m_faultFaceVisibilityFilter = + std::make_unique( RigGridCellFaultFaceVisibilityFilter( mainGrid ) ); + faultGeometryGenerator.setCellVisibility( cellVisibilities ); // Ownership transferred + faultGeometryGenerator.addFaceVisibilityFilter( m_faultFaceVisibilityFilter.get() ); return grpc::Status::OK; } @@ -637,6 +681,24 @@ grpc::Status return grpc::Status( grpc::StatusCode::INVALID_ARGUMENT, "More than one grid case found for project" ); } m_eclipseCase = eclipseCases.front(); + + // Set nncData for main grid + // TODO: Do not perform if calling intersection endpoint only + if ( m_eclipseCase && m_eclipseCase->eclipseCaseData() && m_eclipseCase->eclipseCaseData()->mainGrid() && + m_eclipseCase->eclipseCaseData()->mainGrid()->nncData() ) + { + auto createNncDataForGrid = ElapsedTimeCount(); + const bool includeInactiveCells = true; + m_eclipseCase->eclipseCaseData() + ->mainGrid() + ->nncData() + ->setSourceDataForProcessing( m_eclipseCase->eclipseCaseData()->mainGrid(), + m_eclipseCase->eclipseCaseData()->activeCellInfo( + RiaDefines::PorosityModelType::MATRIX_MODEL ), + includeInactiveCells ); + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateNncDataForGrid"] = + static_cast( createNncDataForGrid.elapsedMsCount() ); + } } if ( m_eclipseCase == nullptr ) diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index f8372a8d5c..f43afe67e9 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -19,6 +19,7 @@ #include "GridGeometryExtraction.grpc.pb.h" #include "RiaApplication.h" +#include "RiaGrpcGridGeometryExtractionServiceHelper.h" #include "RiaGrpcServiceInterface.h" #include "RigGridBase.h" #include "RimEclipseCase.h" @@ -71,12 +72,15 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr grpc::Status applyIJKCellFilterToEclipseView( const rips::IJKIndexFilter& filter, RimEclipseView* view ); grpc::Status initializeApplicationAndEclipseCaseFromAbsoluteFilePath( const std::string filePath ); - grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( cvf::StructGridGeometryGenerator& generator, - RimEclipseView* view ); + grpc::Status initializeGridGeometryGeneratorWithEclipseViewCellVisibility( + cvf::StructGridGeometryGenerator& surfaceGeometryGenerator, + cvf::StructGridGeometryGenerator& faultGeometryGenerator, + RimEclipseView* view ); - RiaApplication* m_application = nullptr; - RimEclipseCase* m_eclipseCase = nullptr; - std::unique_ptr m_faceVisibilityFilter = nullptr; + RiaApplication* m_application = nullptr; + RimEclipseCase* m_eclipseCase = nullptr; + std::unique_ptr m_surfaceFaceVisibilityFilter = nullptr; + std::unique_ptr m_faultFaceVisibilityFilter = nullptr; struct ElapsedTimeInfo { diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.cpp new file mode 100644 index 0000000000..a9d57f5e7b --- /dev/null +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.cpp @@ -0,0 +1,91 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// + +#include "RiaGrpcGridGeometryExtractionServiceHelper.h" + +#include "RigMainGrid.h" +#include "RigNNCData.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RigGridCellFaultFaceVisibilityFilter::isFaceVisible( size_t i, + size_t j, + size_t k, + cvf::StructGridInterface::FaceType face, + const cvf::UByteArray* cellVisibility ) const +{ + CVF_TIGHT_ASSERT( m_grid ); + + size_t cellIndex = m_grid->cellIndexFromIJK( i, j, k ); + size_t nativeResvCellIndex = m_grid->reservoirCellIndex( cellIndex ); + const RigFault* fault = m_grid->mainGrid()->findFaultFromCellIndexAndCellFace( nativeResvCellIndex, face ); + if ( fault ) + { + // TODO: REMOVE EARLY RETURN + return true; // TMP: Until we have a better way to determine if a fault face should be visible + + // If no nnc data is generated, include fault face based on the flag + auto* nncData = m_grid->mainGrid()->nncData(); + if ( nncData == nullptr || nncData->allConnections().empty() ) + { + return true; + } + + // Do not show fault if inside the grid + const auto& faultConnectionIndices = fault->connectionIndices(); + for ( const auto& connectionIndex : faultConnectionIndices ) + { + if ( connectionIndex >= nncData->allConnections().size() ) + { + continue; + } + + const RigConnection& connection = nncData->allConnections()[connectionIndex]; + + size_t oppositeCellIndex = std::numeric_limits::max(); + if ( connection.c1GlobIdx() == cellIndex ) + { + oppositeCellIndex = connection.c2GlobIdx(); + } + else if ( connection.c2GlobIdx() == cellIndex ) + { + oppositeCellIndex = connection.c1GlobIdx(); + } + + if ( oppositeCellIndex >= cellVisibility->size() ) + { + continue; + } + + // TODO: This gives false for all fault faces, is cellVisibility incorrect? + // - Only want to include faults on the boundary of the surface, not the ones inside the grid + // - Now it excludes all, as all opposite cells are visible + // - Seems not to work if fault is on the boundary of the grid? + auto isOppositeCellVisible = ( *cellVisibility )[oppositeCellIndex] != 0; + if ( !isOppositeCellVisible ) + { + return true; + } + } + + // All opposite cells are visible, do not show the fault face + return false; + } + return false; +} diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.h b/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.h new file mode 100644 index 0000000000..c2f35f2911 --- /dev/null +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionServiceHelper.h @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +////////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "RigGridBase.h" + +class RigGridCellFaultFaceVisibilityFilter : public cvf::CellFaceVisibilityFilter +{ +public: + explicit RigGridCellFaultFaceVisibilityFilter( const RigGridBase* const grid ) + : m_grid( grid ) + { + } + + bool isFaceVisible( size_t i, + size_t j, + size_t k, + cvf::StructGridInterface::FaceType face, + const cvf::UByteArray* cellVisibility ) const override; + +private: + const RigGridBase* const m_grid; +}; From 4d87fc5927efe068fdb4a994d51e501da07a697c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 4 Apr 2024 09:03:17 +0200 Subject: [PATCH 40/45] Replace thread count in message box with ria logging info --- ApplicationExeCode/RiaMain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ApplicationExeCode/RiaMain.cpp b/ApplicationExeCode/RiaMain.cpp index 5b490db0b3..b24ebd7036 100644 --- a/ApplicationExeCode/RiaMain.cpp +++ b/ApplicationExeCode/RiaMain.cpp @@ -17,6 +17,7 @@ ///////////////////////////////////////////////////////////////////////////////// #include "RiaArgumentParser.h" +#include "RiaLogging.h" #include "RiaMainTools.h" #include "RiaOpenMPTools.h" #include "RiaPreferences.h" @@ -141,7 +142,7 @@ int main( int argc, char* argv[] ) RiaApplication::ApplicationStatus status = app->handleArguments( &progOpt ); int numOmpThreads = RiaOpenMPTools::numberOfThreads(); - app->showFormattedTextInMessageBoxOrConsole( QString( "OpenMP Num Threads: %1\n" ).arg( numOmpThreads ) ); + RiaLogging::info( QString( "OpenMP Num Threads: %1\n" ).arg( numOmpThreads ) ); if ( status == RiaApplication::ApplicationStatus::EXIT_COMPLETED ) { From 614a9f12136ce4c21036e6bd9981fe3b3cec94a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 4 Apr 2024 09:10:38 +0200 Subject: [PATCH 41/45] Prevent duplicated nodes in vertex array of intersection response --- .../RivEnclosingPolygonGenerator.cpp | 135 +----- .../RivEnclosingPolygonGenerator.h | 49 +-- ...vPolylineIntersectionGeometryGenerator.cpp | 383 +++++++++--------- ...RivPolylineIntersectionGeometryGenerator.h | 12 - .../GrpcProtos/GridGeometryExtraction.proto | 17 +- ..._geometry_extraction_cut_along_polyline.py | 49 ++- .../RiaGrpcGridGeometryExtractionService.cpp | 38 -- 7 files changed, 242 insertions(+), 441 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp index 4e538b3a09..1d95fd552e 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2018- Equinor ASA +// Copyright (C) 2024- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,110 +21,7 @@ #include -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -PolygonVertexWelder::PolygonVertexWelder( double weldEpsilon ) - : m_epsilonSquared( weldEpsilon * weldEpsilon ) - , m_first( cvf::UNDEFINED_UINT ) -{ -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void PolygonVertexWelder::reserveVertices( cvf::uint vertexCount ) -{ - m_vertex.reserve( vertexCount ); - m_next.reserve( vertexCount ); -} - -//-------------------------------------------------------------------------------------------------- -/// Add a vertex to the welder. If the vertex is within the tolerance of an existing vertex, the existing -// vertex index is returned -//-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::weldVertexAndGetIndex( const cvf::Vec3d& vertex ) -{ - // Call function to step through linked list of bucket, testing - // if vertex is within the epsilon of one of the vertices in the bucket - cvf::uint indexOfLocatedVertex = locateVertexInPolygon( vertex ); - if ( indexOfLocatedVertex != cvf::UNDEFINED_UINT ) - { - // if ( wasWelded ) *wasWelded = true; - return indexOfLocatedVertex; - } - - // Vertex not found in epsilon neighborhood, add it to the list - cvf::uint indexOfAddedVertex = addVertexToPolygon( vertex ); - return indexOfAddedVertex; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const cvf::Vec3d& PolygonVertexWelder::vertex( cvf::uint index ) const -{ - return m_vertex[index]; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::ref PolygonVertexWelder::createVertexArray() const -{ - cvf::ref vertexArray = new cvf::Vec3dArray( m_vertex ); - return vertexArray; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::locateVertexInPolygon( const cvf::Vec3d& vertex ) const -{ - cvf::uint currentIndex = m_first; - while ( currentIndex != cvf::UNDEFINED_UINT ) - { - // Weld point within tolerance - const auto distanceSquared = ( m_vertex[currentIndex] - vertex ).lengthSquared(); - if ( distanceSquared < m_epsilonSquared ) - { - return currentIndex; - } - currentIndex = m_next[currentIndex]; - } - - // No vertex found to weld to - return cvf::UNDEFINED_UINT; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::uint PolygonVertexWelder::addVertexToPolygon( const cvf::Vec3d& vertex ) -{ - // Add vertex and update linked list - m_vertex.push_back( vertex ); - m_next.push_back( m_first ); - CVF_TIGHT_ASSERT( m_vertex.size() == m_next.size() ); - - // Update index of first vertex - cvf::uint indexOfAddedVertex = static_cast( m_vertex.size() - 1 ); - m_first = indexOfAddedVertex; - - return indexOfAddedVertex; -} - -//-------------------------------------------------------------------------------------------------- -/// -/// ************************************************************************************************ -/// ************************************************************************************************ -/// ************************************************************************************************ -/// ************************************************************************************************ -/// -//-------------------------------------------------------------------------------------------------- - RivEnclosingPolygonGenerator::RivEnclosingPolygonGenerator() - : m_polygonVertexWelder( 1e-3 ) { } @@ -221,12 +118,7 @@ void RivEnclosingPolygonGenerator::constructEnclosingPolygon() } } - // Convert vertex indices to vertices - m_polygonVertices.clear(); - for ( cvf::uint vertexIndex : enclosingPolygonVertexIndices ) - { - m_polygonVertices.push_back( m_polygonVertexWelder.vertex( vertexIndex ) ); - } + m_polygonVertexIndices = enclosingPolygonVertexIndices; } //-------------------------------------------------------------------------------------------------- @@ -249,9 +141,9 @@ cvf::EdgeKey RivEnclosingPolygonGenerator::findNextEdge( cvf::uint vertexIndex, //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RivEnclosingPolygonGenerator::getPolygonVertices() const +std::vector RivEnclosingPolygonGenerator::getPolygonVertexIndices() const { - return m_polygonVertices; + return m_polygonVertexIndices; } //-------------------------------------------------------------------------------------------------- @@ -263,24 +155,21 @@ bool RivEnclosingPolygonGenerator::isValidPolygon() const } //-------------------------------------------------------------------------------------------------- -/// Add triangle vertices to the polygon. The vertices are welded to prevent duplicated vertices +/// Add triangle vertices to the polygon. The vertex indices are welded and controlled outside +/// of this class. /// -/// Assumes that the vertices are given in counter-clockwise order +/// Assumes the vertices are given in counter-clockwise order //-------------------------------------------------------------------------------------------------- -void RivEnclosingPolygonGenerator::addTriangleVertices( const cvf::Vec3d& p0, const cvf::Vec3d& p1, const cvf::Vec3d& p2 ) +void RivEnclosingPolygonGenerator::addTriangleVertexIndices( cvf::uint idxVx0, cvf::uint idxVx1, cvf::uint idxVx2 ) { - cvf::uint i0 = m_polygonVertexWelder.weldVertexAndGetIndex( p0 ); - cvf::uint i1 = m_polygonVertexWelder.weldVertexAndGetIndex( p1 ); - cvf::uint i2 = m_polygonVertexWelder.weldVertexAndGetIndex( p2 ); - // Verify three unique vertices - i.e. no degenerate triangle - if ( i0 == i1 || i0 == i2 || i1 == i2 ) + if ( idxVx0 == idxVx1 || idxVx0 == idxVx2 || idxVx1 == idxVx2 ) { return; } // Add edges keys to list of all edges - m_allEdgeKeys.emplace_back( cvf::EdgeKey( i0, i1 ).toKeyVal() ); - m_allEdgeKeys.emplace_back( cvf::EdgeKey( i1, i2 ).toKeyVal() ); - m_allEdgeKeys.emplace_back( cvf::EdgeKey( i2, i0 ).toKeyVal() ); + m_allEdgeKeys.emplace_back( cvf::EdgeKey( idxVx0, idxVx1 ).toKeyVal() ); + m_allEdgeKeys.emplace_back( cvf::EdgeKey( idxVx1, idxVx2 ).toKeyVal() ); + m_allEdgeKeys.emplace_back( cvf::EdgeKey( idxVx2, idxVx0 ).toKeyVal() ); } diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h index 36294db6c5..f76d95ba28 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.h @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2018- Equinor ASA +// Copyright (C) 2024- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -18,67 +18,36 @@ #pragma once -#include "cafLine.h" -#include "cvfArray.h" +#include "cvfBase.h" #include "cvfEdgeKey.h" -#include "cvfObject.h" -#include "cvfVector3.h" -#include +#include #include -/* - * Class for handling welding of vertices internally in a polygon to prevent duplicated vertex 3D points within a tolerance margin - */ -class PolygonVertexWelder -{ -public: - PolygonVertexWelder( double weldEpsilon ); - - void reserveVertices( cvf::uint vertexCount ); - - cvf::uint weldVertexAndGetIndex( const cvf::Vec3d& vertex ); - - const cvf::Vec3d& vertex( cvf::uint index ) const; - cvf::ref createVertexArray() const; - -private: - cvf::uint locateVertexInPolygon( const cvf::Vec3d& vertex ) const; - cvf::uint addVertexToPolygon( const cvf::Vec3d& vertex ); - -private: - const double m_epsilonSquared; // Tolerance for vertex welding, radius around vertex defining welding neighborhood - - cvf::uint m_first; // Start of linked list - std::vector m_next; // Links each vertex to next in linked list. Always numVertices long, will grow as vertices are added - std::vector m_vertex; // Unique vertices within tolerance -}; - /* * Class for generating an enclosing polygon from a set of vertices. * - * The class will weld triangle vertices close to each other and provide a vertex index for - * the resulting set of vertices. These indices are used for algorithms constructing the enclosing polygon. + * The class add triangle vertex indices and construct constructing the enclosing polygon from the indices. + * The vertices must be provided in counter clock-wise order. * - * The welding is done using a tolerance value to handle floating point errors. + * The vertex welding, and mapping of vertex indices to vertex 3D points, must be handled externally. */ class RivEnclosingPolygonGenerator { public: RivEnclosingPolygonGenerator(); - std::vector getPolygonVertices() const; + std::vector getPolygonVertexIndices() const; bool isValidPolygon() const; - void addTriangleVertices( const cvf::Vec3d& p0, const cvf::Vec3d& p1, const cvf::Vec3d& p2 ); + void addTriangleVertexIndices( cvf::uint idxVx0, cvf::uint idxVx1, cvf::uint idxVx2 ); void constructEnclosingPolygon(); private: static cvf::EdgeKey findNextEdge( cvf::uint vertextIndex, const std::set& boundaryEdges ); private: - PolygonVertexWelder m_polygonVertexWelder; // Add and weld vertices for a polygon, provides vertex index std::vector m_allEdgeKeys; // Create edge defined by vertex indices when adding triangle. Using cvf::EdgeKey::toKeyVal() - std::vector m_polygonVertices; // List polygon vertices counter clock-wise + std::vector m_polygonVertexIndices; // List polygon vertex indices counter clock-wise }; diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index 1a661a3488..a376f326fd 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -36,7 +36,6 @@ RivPolylineIntersectionGeometryGenerator::RivPolylineIntersectionGeometryGenerat : m_polylineUtm( initializePolylineUtmFromPolylineUtmXy( polylineUtmXy ) ) , m_hexGrid( grid ) { - m_polygonVertices = new cvf::Vec3fArray; } //-------------------------------------------------------------------------------------------------- @@ -66,45 +65,18 @@ std::vector //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const -{ - return m_polylineSegmentsMeshData.size() > 0; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const cvf::Vec3fArray* RivPolylineIntersectionGeometryGenerator::polygonVxes() const -{ - CVF_ASSERT( m_polygonVertices->size() > 0 ); - return m_polygonVertices.p(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivPolylineIntersectionGeometryGenerator::vertiesPerPolygon() const -{ - CVF_ASSERT( m_verticesPerPolygon.size() > 0 ); - return m_verticesPerPolygon; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -const std::vector& RivPolylineIntersectionGeometryGenerator::polygonToCellIndex() const +const std::vector& RivPolylineIntersectionGeometryGenerator::polylineSegmentsMeshData() const { - CVF_ASSERT( m_polygonToCellIdxMap.size() > 0 ); - return m_polygonToCellIdxMap; + CVF_ASSERT( m_polylineSegmentsMeshData.size() > 0 ); + return m_polylineSegmentsMeshData; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -const std::vector& RivPolylineIntersectionGeometryGenerator::polylineSegmentsMeshData() const +bool RivPolylineIntersectionGeometryGenerator::isAnyGeometryPresent() const { - CVF_ASSERT( m_polylineSegmentsMeshData.size() > 0 ); - return m_polylineSegmentsMeshData; + return m_polylineSegmentsMeshData.size() > 0; } //-------------------------------------------------------------------------------------------------- @@ -121,10 +93,7 @@ void RivPolylineIntersectionGeometryGenerator::generateIntersectionGeometry( cvf void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* visibleCells ) { if ( m_hexGrid == nullptr || m_polylineSegmentsMeshData.size() != 0 ) return; - - // Mesh data per polyline segment - std::vector polylineSegmentMeshData = {}; - std::vector calculatedPolygonVertices = {}; + if ( m_polylineUtm.size() < 2 ) return; cvf::BoundingBox gridBBox = m_hexGrid->boundingBox(); const double topDepth = gridBBox.max().z(); @@ -132,181 +101,191 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* const auto zAxisDirection = -cvf::Vec3d::Z_AXIS; // NOTE: Negative or positive direction? const cvf::Vec3d maxHeightVec = zAxisDirection * gridBBox.radius(); - if ( m_polylineUtm.size() > 1 ) + // Weld vertices per polyline segment + // - Low welding distance, as the goal is to weld duplicate vertices + // - Number of buckets is set per segment, utilizing number of cells intersecting the segment + const double weldingDistance = 1.0e-3; + const double weldingCellSize = 4.0 * weldingDistance; + + const size_t numPoints = m_polylineUtm.size(); + size_t pointIdx = 0; + + // Loop over polyline segments + // + // Create intersection geometry for each polyline segment and clip triangles outside the + // polyline segment, using UTM-coordinates. + // + // Afterwards convert to "local" coordinates (p1 as origin), where the local uz-coordinates + // for each vertex is calculated using Pythagoras theorem. + // + // As the plane is parallel to the z-axis, the local uz-coordinates per polyline segment + // can be calculated using Pythagoras theorem. Where a segment is defined between p1 and p2, + // which implies p1 is origin of the local coordinate system uz. + // + // For a segment a UTM coordinate (x_utm,y_utm,z_utm) converts to u = sqrt(x^2 + y^2) and z = z. + // Where x, y and z are local vertex coordinates, after subtracting the (x_utm, y_utm, z_utm)-values + // for p1 from the vertex UTM-coordinates. + while ( pointIdx < numPoints - 1 ) { - const size_t numPoints = m_polylineUtm.size(); - size_t pointIdx = 0; - - // Loop over polyline segments - // - // Create intersection geometry for each polyline segment and clip triangles outside the - // polyline segment, using UTM-coordinates. - // - // Afterwards convert to "local" coordinates (p1 as origin), where the local uz-coordinates - // for each vertex is calculated using Pythagoras theorem. - // - // As the plane is parallel to the z-axis, the local uz-coordinates per polyline segment - // can be calculated using Pythagoras theorem. Where a segment is defined between p1 and p2, - // which implies p1 is origin of the local coordinate system uz. - // - // For a segment a UTM coordinate (x_utm,y_utm,z_utm) converts to u = sqrt(x^2 + y^2) and z = z. - // Where x, y and z are local vertex coordinates, after subtracting the (x_utm, y_utm, z_utm)-values - // for p1 from the vertex UTM-coordinates. - while ( pointIdx < numPoints - 1 ) + size_t nextPointIdx = RivSectionFlattener::indexToNextValidPoint( m_polylineUtm, zAxisDirection, pointIdx ); + if ( nextPointIdx == size_t( -1 ) || nextPointIdx >= m_polylineUtm.size() ) { - size_t nextPointIdx = RivSectionFlattener::indexToNextValidPoint( m_polylineUtm, zAxisDirection, pointIdx ); - if ( nextPointIdx == size_t( -1 ) || nextPointIdx >= m_polylineUtm.size() ) + break; + } + + // Start and end point of polyline segment in UTM-coordinates + const cvf::Vec3d p1 = m_polylineUtm[pointIdx]; + const cvf::Vec3d p2 = m_polylineUtm[nextPointIdx]; + + // Get cell candidates for the polyline segment (subset of global cells) + std::vector columnCellCandidates = + createPolylineSegmentCellCandidates( *m_hexGrid, p1, p2, maxHeightVec, topDepth, bottomDepth ); + + // Plane for the polyline segment + cvf::Plane plane; + plane.setFromPoints( p1, p2, p2 + maxHeightVec ); + + // Planes parallel to z-axis for p1 and p2, to prevent triangles outside the polyline segment + cvf::Plane p1Plane; + p1Plane.setFromPoints( p1, p1 + maxHeightVec, p1 + plane.normal() ); + cvf::Plane p2Plane; + p2Plane.setFromPoints( p2, p2 + maxHeightVec, p2 - plane.normal() ); + + // Placeholder for triangle vertices per cell + std::vector hexPlaneCutTriangleVxes; + hexPlaneCutTriangleVxes.reserve( 5 * 3 ); + std::vector cellFaceForEachTriangleEdge; + cellFaceForEachTriangleEdge.reserve( 5 * 3 ); + cvf::Vec3d cellCorners[8]; + size_t cornerIndices[8]; + + // Polyline segment data + std::vector polygonIndices = {}; + std::vector verticesPerPolygon = {}; + std::vector polygonToCellIndexMap = {}; + + // Welder for segment vertices + // - Number of buckets is size of columnCellCandidates divided by 8 to avoid too many buckets (Random selected value). + // Usage of columnCellCandidates is to get a dynamic number of buckets usable for respective segment. + const cvf::uint numWelderBuckets = static_cast( columnCellCandidates.size() / size_t( 8 ) ); + cvf::VertexWelder segmentVertexWelder; + segmentVertexWelder.initialize( weldingDistance, weldingCellSize, numWelderBuckets ); + + // Intersection per grid cell - transform from set of triangles to polygon for cell + for ( const auto globalCellIdx : columnCellCandidates ) + { + if ( ( visibleCells != nullptr ) && ( ( *visibleCells )[globalCellIdx] == 0 ) ) continue; + if ( !m_hexGrid->useCell( globalCellIdx ) ) continue; + + // Perform intersection and clipping of triangles using UTM-coordinates + hexPlaneCutTriangleVxes.clear(); + m_hexGrid->cellCornerVertices( globalCellIdx, cellCorners ); + m_hexGrid->cellCornerIndices( globalCellIdx, cornerIndices ); + + // Triangle vertices for polyline segment + caf::HexGridIntersectionTools::planeHexIntersectionMC( plane, + cellCorners, + cornerIndices, + &hexPlaneCutTriangleVxes, + &cellFaceForEachTriangleEdge ); + + // Clip triangles outside the polyline segment using the planes for point p1 and p2 + std::vector clippedTriangleVxes; + std::vector cellFaceForEachClippedTriangleEdge; + + caf::HexGridIntersectionTools::clipTrianglesBetweenTwoParallelPlanes( hexPlaneCutTriangleVxes, + cellFaceForEachTriangleEdge, + p1Plane, + p2Plane, + &clippedTriangleVxes, + &cellFaceForEachClippedTriangleEdge ); + + for ( caf::HexGridIntersectionTools::ClipVx& clvx : clippedTriangleVxes ) + { + if ( !clvx.isVxIdsNative ) clvx.derivedVxLevel = 0; + } + + // Object to for adding triangle vertices, well vertices and generate polygon vertices + RivEnclosingPolygonGenerator enclosingPolygonGenerator; + + // Add clipped triangle vertices to the polygon generator using local coordinates + size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; + for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) { - break; + // Get triangle vertices + const size_t tVxIdx0 = triangleIdx * 3; + const auto& tVx0 = clippedTriangleVxes[tVxIdx0 + 0].vx; + const auto& tVx1 = clippedTriangleVxes[tVxIdx0 + 1].vx; + const auto& tVx2 = clippedTriangleVxes[tVxIdx0 + 2].vx; + + // TODO: Ensure counter clockwise order of vertices point0, point1, point2? + + // Convert to local coordinates, where p1 is origin. + // The z-values are global z-values in the uz-coordinates. + const cvf::Vec3f vx0( tVx0.x() - p1.x(), tVx0.y() - p1.y(), tVx0.z() ); + const cvf::Vec3f vx1( tVx1.x() - p1.x(), tVx1.y() - p1.y(), tVx1.z() ); + const cvf::Vec3f vx2( tVx2.x() - p1.x(), tVx2.y() - p1.y(), tVx2.z() ); + + // Weld vertices and get vertex index + bool isWelded = false; + const auto& wVxIdx0 = segmentVertexWelder.weldVertex( vx0, &isWelded ); + const auto& wVxIdx1 = segmentVertexWelder.weldVertex( vx1, &isWelded ); + const auto& wVxIdx2 = segmentVertexWelder.weldVertex( vx2, &isWelded ); + + // Add triangle to enclosing polygon line handler + enclosingPolygonGenerator.addTriangleVertexIndices( wVxIdx0, wVxIdx1, wVxIdx2 ); } - // Start and end point of polyline segment in UTM-coordinates - const cvf::Vec3d p1 = m_polylineUtm[pointIdx]; - const cvf::Vec3d p2 = m_polylineUtm[nextPointIdx]; - - // Get cell candidates for the polyline segment (subset of global cells) - std::vector columnCellCandidates = - createPolylineSegmentCellCandidates( *m_hexGrid, p1, p2, maxHeightVec, topDepth, bottomDepth ); - - // Plane for the polyline segment - cvf::Plane plane; - plane.setFromPoints( p1, p2, p2 + maxHeightVec ); - - // Planes parallel to z-axis for p1 and p2, to prevent triangles outside the polyline segment - cvf::Plane p1Plane; - p1Plane.setFromPoints( p1, p1 + maxHeightVec, p1 + plane.normal() ); - cvf::Plane p2Plane; - p2Plane.setFromPoints( p2, p2 + maxHeightVec, p2 - plane.normal() ); - - // Placeholder for triangle vertices per cell - std::vector hexPlaneCutTriangleVxes; - hexPlaneCutTriangleVxes.reserve( 5 * 3 ); - std::vector cellFaceForEachTriangleEdge; - cellFaceForEachTriangleEdge.reserve( 5 * 3 ); - cvf::Vec3d cellCorners[8]; - size_t cornerIndices[8]; - - // Mesh data for polyline segment - std::vector polygonVerticesUz = {}; - std::vector verticesPerPolygon = {}; - std::vector polygonToCellIndexMap = {}; - - // Handle triangles per cell - for ( const auto globalCellIdx : columnCellCandidates ) + // Must be a valid polygon to continue + if ( !enclosingPolygonGenerator.isValidPolygon() ) { - if ( ( visibleCells != nullptr ) && ( ( *visibleCells )[globalCellIdx] == 0 ) ) continue; - if ( !m_hexGrid->useCell( globalCellIdx ) ) continue; - - // Perform intersection and clipping of triangles using UTM-coordinates - hexPlaneCutTriangleVxes.clear(); - m_hexGrid->cellCornerVertices( globalCellIdx, cellCorners ); - m_hexGrid->cellCornerIndices( globalCellIdx, cornerIndices ); - - // Triangle vertices for polyline segment - caf::HexGridIntersectionTools::planeHexIntersectionMC( plane, - cellCorners, - cornerIndices, - &hexPlaneCutTriangleVxes, - &cellFaceForEachTriangleEdge ); - - // Clip triangles outside the polyline segment using the planes for point p1 and p2 - std::vector clippedTriangleVxes; - std::vector cellFaceForEachClippedTriangleEdge; - - caf::HexGridIntersectionTools::clipTrianglesBetweenTwoParallelPlanes( hexPlaneCutTriangleVxes, - cellFaceForEachTriangleEdge, - p1Plane, - p2Plane, - &clippedTriangleVxes, - &cellFaceForEachClippedTriangleEdge ); - - for ( caf::HexGridIntersectionTools::ClipVx& clvx : clippedTriangleVxes ) - { - if ( !clvx.isVxIdsNative ) clvx.derivedVxLevel = 0; - } - - // Object to for adding triangle vertices, well vertices and generate polygon vertices - RivEnclosingPolygonGenerator enclosingPolygonGenerator; - - // Add clipped triangle vertices to the polygon generator using local coordinates - size_t clippedTriangleCount = clippedTriangleVxes.size() / 3; - for ( size_t triangleIdx = 0; triangleIdx < clippedTriangleCount; ++triangleIdx ) - { - // Get triangle vertices - const size_t vxIdx0 = triangleIdx * 3; - const auto& vx0 = clippedTriangleVxes[vxIdx0 + 0].vx; - const auto& vx1 = clippedTriangleVxes[vxIdx0 + 1].vx; - const auto& vx2 = clippedTriangleVxes[vxIdx0 + 2].vx; - - // Convert to local coordinates, where p1 is origin. - // The z-values are global z-values in the uz-coordinates. - const cvf::Vec3d point0( vx0.x() - p1.x(), vx0.y() - p1.y(), vx0.z() ); - const cvf::Vec3d point1( vx1.x() - p1.x(), vx1.y() - p1.y(), vx1.z() ); - const cvf::Vec3d point2( vx2.x() - p1.x(), vx2.y() - p1.y(), vx2.z() ); - - // TODO: Ensure counter clockwise order of vertices point0, point1, point2? - - // Add triangle to enclosing polygon line handler - enclosingPolygonGenerator.addTriangleVertices( point0, point1, point2 ); - } - - // Must be a valid polygon to continue - if ( !enclosingPolygonGenerator.isValidPolygon() ) - { - continue; - } - - // Construct enclosing polygon after adding each triangle - enclosingPolygonGenerator.constructEnclosingPolygon(); - const auto& vertices = enclosingPolygonGenerator.getPolygonVertices(); - - // Construct local uz-coordinates using Pythagoras theorem - for ( const auto& vertex : vertices ) - { - // NOTE: Can welding provide drifting of vertex positions? - // TODO: Project (x,y) into plane instead? - // - // Convert to local uz-coordinates, u is the distance along the normalized U-axis - const auto u = std::sqrt( vertex.x() * vertex.x() + vertex.y() * vertex.y() ); - const auto z = vertex.z(); - - polygonVerticesUz.push_back( u ); - polygonVerticesUz.push_back( z ); - - // Keep old code for debugging purposes - calculatedPolygonVertices.push_back( cvf::Vec3f( vertex + p1 ) ); - } - verticesPerPolygon.push_back( static_cast( vertices.size() ) ); - polygonToCellIndexMap.push_back( static_cast( globalCellIdx ) ); - - // Keep old code for debugging purposes - m_verticesPerPolygon.push_back( vertices.size() ); // TODO: Remove when not needed for debug - m_polygonToCellIdxMap.push_back( globalCellIdx ); // TODO: Remove when not needed for debug + continue; } - // Create polygon indices array - const auto numVertices = static_cast( polygonVerticesUz.size() / 2 ); - std::vector polygonIndices( numVertices ); - std::iota( polygonIndices.begin(), polygonIndices.end(), 0 ); - - // Construct polyline segment mesh data - PolylineSegmentMeshData polylineSegmentData; - polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); - polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); - polylineSegmentData.vertexArrayUZ = polygonVerticesUz; - polylineSegmentData.verticesPerPolygon = verticesPerPolygon; - polylineSegmentData.polygonIndices = polygonIndices; - polylineSegmentData.polygonToCellIndexMap = polygonToCellIndexMap; - - // Add polyline segment mesh data to list - m_polylineSegmentsMeshData.push_back( polylineSegmentData ); - - // Set next polyline segment start index - pointIdx = nextPointIdx; + // Construct enclosing polygon after adding all triangles for cell + enclosingPolygonGenerator.constructEnclosingPolygon(); + + // Add vertex index to polygon indices + const auto& vertexIndices = enclosingPolygonGenerator.getPolygonVertexIndices(); + polygonIndices.insert( polygonIndices.end(), vertexIndices.begin(), vertexIndices.end() ); + + verticesPerPolygon.push_back( static_cast( vertexIndices.size() ) ); + polygonToCellIndexMap.push_back( static_cast( globalCellIdx ) ); } - } - m_polygonVertices->assign( calculatedPolygonVertices ); // TODO: Remove when not needed for debug + // Build vertex array for polyline segment + std::vector polygonVerticesUz; + for ( cvf::uint i = 0; i < segmentVertexWelder.vertexCount(); i++ ) + { + const auto& vertex = segmentVertexWelder.vertex( i ); + // NOTE: Can welding provide drifting of vertex positions? + // TODO: Project (x,y) into plane instead? + // + // auto projectedVertex = plane.projectPoint( vertex ); + + // Convert to local uz-coordinates, u is the distance along the normalized U-axis. + // Construct local uz-coordinates using Pythagoras theorem + const auto u = std::sqrt( vertex.x() * vertex.x() + vertex.y() * vertex.y() ); + const auto z = vertex.z(); + polygonVerticesUz.push_back( u ); + polygonVerticesUz.push_back( z ); + } + + // Construct polyline segment mesh data + PolylineSegmentMeshData polylineSegmentData; + polylineSegmentData.startUtmXY = cvf::Vec2d( p1.x(), p1.y() ); + polylineSegmentData.endUtmXY = cvf::Vec2d( p2.x(), p2.y() ); + polylineSegmentData.vertexArrayUZ = polygonVerticesUz; + polylineSegmentData.verticesPerPolygon = verticesPerPolygon; + polylineSegmentData.polygonIndices = polygonIndices; + polylineSegmentData.polygonToCellIndexMap = polygonToCellIndexMap; + + // Add polyline segment mesh data to list + m_polylineSegmentsMeshData.push_back( polylineSegmentData ); + + // Set next polyline segment start index + pointIdx = nextPointIdx; + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h index 85ff677f16..667c8d97cd 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.h @@ -26,8 +26,6 @@ #include -#include - class RigMainGrid; class RigActiveCellInfo; class RigResultAccessor; @@ -60,11 +58,6 @@ class RivPolylineIntersectionGeometryGenerator void generateIntersectionGeometry( cvf::UByteArray* visibleCells ); bool isAnyGeometryPresent() const; - // TODO: Remove after testing? - const cvf::Vec3fArray* polygonVxes() const; - const std::vector& vertiesPerPolygon() const; - const std::vector& polygonToCellIndex() const; - const std::vector& polylineSegmentsMeshData() const; private: @@ -84,9 +77,4 @@ class RivPolylineIntersectionGeometryGenerator // Output std::vector m_polylineSegmentsMeshData; - - // TMP Output arrays for debug - std::vector m_polygonToCellIdxMap; - cvf::ref m_polygonVertices; - std::vector m_verticesPerPolygon; }; diff --git a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto index ec0f517d9d..31722e8c87 100644 --- a/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto +++ b/GrpcInterface/GrpcProtos/GridGeometryExtraction.proto @@ -68,27 +68,18 @@ message CutAlongPolylineRequest message FenceMeshSection { // U-axis defined by the unit length vector from start to end, Z is global Z - repeated float vertexArrayUZ = 1; // U coordinate is length along U-axis - repeated fixed32 polyIndicesArr = 2; // Note: Redundant if no shared nodes? + repeated float vertexArrayUZ = 1; // U coordinate is length along U-axis. Unique vertex coordinates (u,z). Stored [u0, z0, u1, z1, ...] + repeated fixed32 polyIndicesArr = 2; // Polygon vertex indices. Index of vertex (u,z) in the unique vertex coordinate array. repeated fixed32 verticesPerPolygonArr = 3; // Number of vertices per polygon, numPolygons long repeated fixed32 sourceCellIndicesArr = 4; // The originating cell index per polygon, numPolygons long Vec2d startUtmXY = 6; Vec2d endUtmXY = 7; } -message PolylineTestResponse -{ - // Test response returning all vertices without "local" section coordinates - repeated float polygonVertexArray = 1; - repeated fixed32 verticesPerPolygonArr = 2; // Number of vertices per polygon, numPolygons long - repeated fixed32 sourceCellIndicesArr = 3; // The originating cell index per polygon, numPolygons long -} - message CutAlongPolylineResponse { repeated FenceMeshSection fenceMeshSections = 1; - PolylineTestResponse polylineTestResponse = 2; - TimeElapsedInfo timeElapsedInfo = 3; - Vec3i gridDimensions = 4; + TimeElapsedInfo timeElapsedInfo = 2; + Vec3i gridDimensions = 3; } diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index 72469193a1..408450d219 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -44,7 +44,7 @@ # fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy -fence_poly_line_utm_xy = norne_case_single_segment_poly_line_gap_utm_xy +fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( gridFilename=grid_file_name, @@ -68,10 +68,20 @@ # Use first segment start (x,y) as origin x_origin = fence_mesh_sections[0].startUtmXY.x if len(fence_mesh_sections) > 0 else 0 y_origin = fence_mesh_sections[0].startUtmXY.y if len(fence_mesh_sections) > 0 else 0 + +section_number = 1 for section in fence_mesh_sections: # Continue to next section polygon_vertex_array_uz = section.vertexArrayUZ vertices_per_polygon = section.verticesPerPolygonArr + polygon_indices_array = section.polyIndicesArr + + num_vertices = sum(vertices_per_polygon) + print(f"**** Section number: {section_number} ****") + print(f"Number of vertices in vertex uz array: {len(polygon_vertex_array_uz)/2}") + print(f"Number of polygon vertices: {len(polygon_indices_array)}") + print(f"Number of vertices: {num_vertices}") + section_number += 1 # Get start and end coordinates (local coordinates) start_x = section.startUtmXY.x - x_origin @@ -94,18 +104,31 @@ x_array = [] y_array = [] z_array = [] - for i in range(0, len(polygon_vertex_array_uz), vertex_step): - u = polygon_vertex_array_uz[i] - z = polygon_vertex_array_uz[i + 1] - - # Calculate x, y from u and directional vector, - # where u is the length along the direction vector - x = start_x + u * direction_vector_norm[0] - y = start_y + u * direction_vector_norm[1] - - x_array.append(x) - y_array.append(y) - z_array.append(z) + + vertex_offset = 0 + for _, value in enumerate(vertices_per_polygon, 0): + num_polygon_vertices = value + polygon_indices = polygon_indices_array[ + vertex_offset : vertex_offset + num_polygon_vertices + ] + + for vertex_idx in polygon_indices: + idx = vertex_idx * vertex_step + + # Extract u, z values for the polygon + u = polygon_vertex_array_uz[idx] + z = polygon_vertex_array_uz[idx + 1] + + # Calculate x, y from u and directional vector, + # where u is the length along the direction vector + x = start_x + u * direction_vector_norm[0] + y = start_y + u * direction_vector_norm[1] + + x_array.append(x) + y_array.append(y) + z_array.append(z) + + vertex_offset = vertex_offset + num_polygon_vertices i = [] j = [] diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index fc5912daec..8ad579c440 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -366,44 +366,6 @@ grpc::Status RiaGrpcGridGeometryExtractionService::CutAlongPolyline( grpc::Serve m_elapsedTimeInfo.elapsedTimePerEventMs["FillResponse"] = static_cast( fillResponseTimeCount.elapsedMsCount() ); - // Add temporary test response - { - auto fillTestResponseTimeCount = ElapsedTimeCount(); - rips::PolylineTestResponse* polylineTestResponse = new rips::PolylineTestResponse; - - // Polygon vertices - const auto& polygonVertices = polylineIntersectionGenerator.polygonVxes(); - if ( polygonVertices->size() == 0 ) - { - return grpc::Status( grpc::StatusCode::NOT_FOUND, "No polygon vertices found for polyline" ); - } - for ( size_t i = 0; i < polygonVertices->size(); ++i ) - { - const auto& vertex = polygonVertices->get( i ); - polylineTestResponse->add_polygonvertexarray( vertex.x() ); - polylineTestResponse->add_polygonvertexarray( vertex.y() ); - polylineTestResponse->add_polygonvertexarray( vertex.z() ); - } - - // Vertices per polygon - const auto& verticesPerPolygon = polylineIntersectionGenerator.vertiesPerPolygon(); - for ( const auto& elm : verticesPerPolygon ) - { - polylineTestResponse->add_verticesperpolygonarr( static_cast( elm ) ); - } - - // Polygon to cell indices - const auto& polygonCellIndices = polylineIntersectionGenerator.polygonToCellIndex(); - for ( const auto& elm : polygonCellIndices ) - { - polylineTestResponse->add_sourcecellindicesarr( static_cast( elm ) ); - } - - response->set_allocated_polylinetestresponse( polylineTestResponse ); - m_elapsedTimeInfo.elapsedTimePerEventMs["FillResponse"] = - static_cast( fillTestResponseTimeCount.elapsedMsCount() ); - } - // Clear existing view tearDownExistingViewsInEclipseCase(); From d552c1bbd23a99955a93d3901eb5881ba1e4c3aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 4 Apr 2024 13:39:00 +0200 Subject: [PATCH 42/45] Weld vertices in GetGridSurface endpoint - Weld vertices to prevent duplicated nodes in vertex array. - Handle welding of surface vertices and fault vertices separately. - Adjust and remove python code --- ...on_cut_along_polyline_MULTIPLE_REQUESTS.py | 6 +- ...action_cut_along_polyline_TEST_RESPONSE.py | 247 ------------------ ...on_cut_along_polyline_TRIANGLE_VERTICES.py | 99 ------- ...traction_get_grid_surface POLYGON_COUNT.py | 5 +- ...id_geometry_extraction_get_grid_surface.py | 16 +- ...tion_get_grid_surface_MULTIPLE_REQUESTS.py | 4 +- .../RiaGrpcGridGeometryExtractionService.cpp | 63 ++++- .../RiaGrpcGridGeometryExtractionService.h | 3 + 8 files changed, 74 insertions(+), 369 deletions(-) delete mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py delete mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py index c83078bb9a..936892604f 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_MULTIPLE_REQUESTS.py @@ -56,8 +56,8 @@ GridGeometryExtraction__pb2.CutAlongPolylineResponse ) = grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) - # fence_mesh_sections = cut_along_polyline_response.fenceMeshSections - # print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") - # time.sleep(sleep_time_s) + fence_mesh_sections = cut_along_polyline_response.fenceMeshSections + print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") + time.sleep(sleep_time_s) print("Done!") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py deleted file mode 100644 index 84da2874fa..0000000000 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TEST_RESPONSE.py +++ /dev/null @@ -1,247 +0,0 @@ -import numpy as np - -import plotly.graph_objects as go - -from rips.instance import * -from rips.generated.GridGeometryExtraction_pb2_grpc import * -from rips.generated.GridGeometryExtraction_pb2 import * - -# from ..instance import * -# from ..generated.GridGeometryExtraction_pb2_grpc import * -# from ..generated.GridGeometryExtraction_pb2 import * - -rips_instance = Instance.find() -grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) - -grid_file_name = "MOCKED_TEST_GRID" -grid_file_name = ( - "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" -) - -# Test polylines -mocked_model_fence_poly_line_utm_xy = [ - 11.2631, - 11.9276, - 14.1083, - 18.2929, - 18.3523, - 10.9173, -] -norne_case_fence_poly_line_utm_xy = [ - 456221, - 7.32113e06, - 457150, - 7.32106e06, - 456885, - 7.32176e06, - 457648, - 7.3226e06, - 458805, - 7.32278e06, -] -norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.32176e06] -norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] - - -fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy - -cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( - gridFilename=grid_file_name, - fencePolylineUtmXY=fence_poly_line_utm_xy, -) -cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( - grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) -) - -polygon_vertex_array_org = ( - cut_along_polyline_response.polylineTestResponse.polygonVertexArray -) -vertices_per_polygon = ( - cut_along_polyline_response.polylineTestResponse.verticesPerPolygonArr -) -source_cell_indices = ( - cut_along_polyline_response.polylineTestResponse.sourceCellIndicesArr -) - -x_start = polygon_vertex_array_org[0] -y_start = polygon_vertex_array_org[1] -z_start = polygon_vertex_array_org[2] - -# Subtract x_start, y_start, z_start from all x, y, z coordinates -polygon_vertex_array = [] -for i in range(0, len(polygon_vertex_array_org), 3): - polygon_vertex_array.extend( - [ - polygon_vertex_array_org[i] - x_start, - polygon_vertex_array_org[i + 1] - y_start, - polygon_vertex_array_org[i + 2] - z_start, - ] - ) - -num_vertex_coords = 3 # [x, y, z] - -# Create x-, y-, and z-arrays -x_array = [] -y_array = [] -z_array = [] -for i in range(0, len(polygon_vertex_array), num_vertex_coords): - # vertex array is provided as a single array of x, y, z coordinates - # i.e. [x1, y1, z1, x2, y2, z2, x3, y3, z3, ... , xn, yn, zn] - x_array.append(polygon_vertex_array[i + 0]) - y_array.append(polygon_vertex_array[i + 1]) - z_array.append(polygon_vertex_array[i + 2]) - -# Create triangular mesh -vertices = np.array(polygon_vertex_array).reshape(-1, 3) - -# Create mesh data -x, y, z = vertices.T -i = [] -j = [] -k = [] - -# Create edges between points in triangles -triangle_edges_x = [] -triangle_edges_y = [] -triangle_edges_z = [] - -# Populate i, j, k based on vertices_per_polygon -# Create triangles from each polygon -# A quad with vertex [0,1,2,3] will be split into two triangles [0,1,2] and [0,2,3] -# A hexagon with vertex [0,1,2,3,4,5] will be split into four triangles [0,1,2], [0,2,3], [0,3,4], [0,4,5] - -polygon_v0_idx = 0 # Index of vertex 0 in the polygon -for vertex_count in vertices_per_polygon: - # Must have at least one triangle - if vertex_count < 3: - polygon_v0_idx += vertex_count - continue - - indices = list(range(polygon_v0_idx, polygon_v0_idx + vertex_count)) - - # Build triangles from polygon - num_triangles = vertex_count - 2 - for triangle_index in range(0, num_triangles): - triangle_v0_idx = polygon_v0_idx - triangle_v1_idx = indices[triangle_index + 1] - triangle_v2_idx = indices[triangle_index + 2] - - # Vertex indices for the triangle - i.append(triangle_v0_idx) - j.append(triangle_v1_idx) - k.append(triangle_v2_idx) - - # Create edge between vertices in triangle with x,y,z coordinates, coordinates per vertex is 3 - coordinate_step = 3 # step per vertex - triangle_v0_global_idx = triangle_v0_idx * coordinate_step - triangle_v1_global_idx = triangle_v1_idx * coordinate_step - triangle_v2_global_idx = triangle_v2_idx * coordinate_step - - # Add x,y,z coordinates for the triangle vertices (closing triangle with 'None') - triangle_edges_x.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 0], - polygon_vertex_array[triangle_v1_global_idx + 0], - polygon_vertex_array[triangle_v2_global_idx + 0], - polygon_vertex_array[triangle_v0_global_idx + 0], - None, - ] - ) - triangle_edges_y.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 1], - polygon_vertex_array[triangle_v1_global_idx + 1], - polygon_vertex_array[triangle_v2_global_idx + 1], - polygon_vertex_array[triangle_v0_global_idx + 1], - None, - ] - ) - triangle_edges_z.extend( - [ - polygon_vertex_array[triangle_v0_global_idx + 2], - polygon_vertex_array[triangle_v1_global_idx + 2], - polygon_vertex_array[triangle_v2_global_idx + 2], - polygon_vertex_array[triangle_v0_global_idx + 2], - None, - ] - ) - - # Move to next polygon - polygon_v0_idx += vertex_count - -# Create edges between points in polygons -polygon_edges_x = [] -polygon_edges_y = [] -polygon_edges_z = [] -polygon_global_start_index = 0 -coordinate_step = 3 # step per vertex -for vertex_count in vertices_per_polygon: - # Must have at least a triangle - if vertex_count < 3: - polygon_global_start_index += vertex_count * coordinate_step - continue - - for vertex_idx in range(0, vertex_count): - vertex_global_idx = polygon_global_start_index + vertex_idx * coordinate_step - polygon_edges_x.append(polygon_vertex_array[vertex_global_idx + 0]) - polygon_edges_y.append(polygon_vertex_array[vertex_global_idx + 1]) - polygon_edges_z.append(polygon_vertex_array[vertex_global_idx + 2]) - - # Close the polygon - polygon_edges_x.append(polygon_vertex_array[polygon_global_start_index + 0]) - polygon_edges_y.append(polygon_vertex_array[polygon_global_start_index + 1]) - polygon_edges_z.append(polygon_vertex_array[polygon_global_start_index + 2]) - - polygon_edges_x.append(None) - polygon_edges_y.append(None) - polygon_edges_z.append(None) - - polygon_global_start_index += vertex_count * coordinate_step - - -# Create mesh -mesh_3D = go.Mesh3d( - x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.8, color="rgba(244,22,100,0.6)" -) - -# Create edge lines for triangles -triangle_edges_3d = go.Scatter3d( - x=triangle_edges_x, - y=triangle_edges_y, - z=triangle_edges_z, - mode="lines", - name="", - line=dict(color="rgb(0,0,0)", width=1), -) - -# Create outer edge lines for polygon -polygon_edges_3d = go.Scatter3d( - x=polygon_edges_x, - y=polygon_edges_y, - z=polygon_edges_z, - mode="lines", - name="", - line=dict(color="rgb(0,0,0)", width=1), -) - -fig = go.Figure( - data=[ - mesh_3D, - # triangle_edges_3d, - polygon_edges_3d, - ] -) - -# print(f"j array: {j_array}") -# print(f"Number of vertices: {len(vertex_array) / 3}") -# print(f"Number of traingles: {num_triangles}") -# print(f"Source cell indices array length: {len(source_cell_indices_arr)}") -# print( -# f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" -# ) -# print( -# f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" -# ) -print(fig.data) - -fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py deleted file mode 100644 index dbe5d4fe1c..0000000000 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline_TRIANGLE_VERTICES.py +++ /dev/null @@ -1,99 +0,0 @@ -import numpy as np - -import plotly.graph_objects as go - -from rips.instance import * -from rips.generated.GridGeometryExtraction_pb2_grpc import * -from rips.generated.GridGeometryExtraction_pb2 import * - -# from ..instance import * -# from ..generated.GridGeometryExtraction_pb2_grpc import * -# from ..generated.GridGeometryExtraction_pb2 import * - -rips_instance = Instance.find() -grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) - -grid_file_name = "MOCKED_TEST_GRID" -fence_poly_line_utm_xy = [11.2631, 11.9276, 14.1083, 18.2929, 18.3523, 10.9173] - -cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( - gridFilename=grid_file_name, - fencePolylineUtmXY=fence_poly_line_utm_xy, -) -cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( - grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) -) - -vertex_array = cut_along_polyline_response.polylineTestResponse.triangleVertexArray -cut_along_polyline_response.polylineTestResponse - -num_vertex_coords = 3 # [x, y, z] -num_vertices_per_triangle = 3 # [v1, v2, v3] -num_triangles = len(vertex_array) / (num_vertex_coords * num_vertices_per_triangle) - -# Create x-, y-, and z-arrays -x_array = [] -y_array = [] -z_array = [] -for i in range(0, len(vertex_array), num_vertex_coords): - x_array.append(vertex_array[i + 0]) - y_array.append(vertex_array[i + 1]) - z_array.append(vertex_array[i + 2]) - -# Create triangular mesh -i_array = [] -j_array = [] -k_array = [] -for i in range(0, len(x_array), num_vertices_per_triangle): - # Set the indices of the vertices of the triangles - i_array.extend([i + 0]) - j_array.extend([i + 1]) - k_array.extend([i + 2]) - -mesh_3d = go.Mesh3d( - x=x_array, - y=y_array, - z=z_array, - i=i_array, - j=j_array, - k=k_array, - intensity=np.linspace(-5, 5, 1000, endpoint=True), - showscale=True, - colorscale=[[0, "gold"], [0.5, "mediumturquoise"], [1.0, "magenta"]], -) - -# Create edges between points in triangles -Xe = [] -Ye = [] -Ze = [] -step_per_triangle = num_vertex_coords * num_vertices_per_triangle -for i in range(0, len(vertex_array), step_per_triangle): - Xe.extend( - [vertex_array[i + 0], vertex_array[i + 3], vertex_array[i + 6], None] - ) # x-coordinates of start and end points of the edge - Ye.extend( - [vertex_array[i + 1], vertex_array[i + 4], vertex_array[i + 7], None] - ) # y-coordinates of start and end points of the edge - Ze.extend( - [vertex_array[i + 2], vertex_array[i + 5], vertex_array[i + 8], None] - ) # z-coordinates of start and end points of the edge - -edges_3d = go.Scatter3d( - x=Xe, y=Ye, z=Ze, mode="lines", name="", line=dict(color="rgb(70,70,70)", width=1) -) - -fig = go.Figure(data=[mesh_3d, edges_3d]) - -print(f"j array: {j_array}") -print(f"Number of vertices: {len(vertex_array) / 3}") -print(f"Number of traingles: {num_triangles}") -# print(f"Source cell indices array length: {len(source_cell_indices_arr)}") -# print( -# f"Origin UTM coordinates [x, y, z]: [{origin_utm.x}, {origin_utm.y}, {origin_utm.z}]" -# ) -# print( -# f"Grid dimensions [I, J, K]: [{grid_dimensions.dimensions.i}, {grid_dimensions.dimensions.j}, {grid_dimensions.dimensions.k}]" -# ) -print(fig.data) - -fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py index 910fd95d3d..b4ec323662 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface POLYGON_COUNT.py @@ -47,10 +47,13 @@ num_vertex_coords = 3 # [x, y, z] num_vertices_per_quad = 4 # [v1, v2, v3, v4] -num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad) +num_quads = len(quad_indices_array) / num_vertices_per_quad +print(f"Number of vertices in vertex array: {len(vertex_array) / 3}") +print(f"Number of quad vertices: {len(quad_indices_array)}") print(f"Number of quads: {num_quads}") + print(f"Source cell indices array length: {len(source_cell_indices_arr)}") print(f"Origin UTM coordinates [x, y]: [{origin_utm_xy.x}, {origin_utm_xy.y}]") print( diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 7e9e442269..13ab667899 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -41,22 +41,23 @@ vertex_array = get_grid_surface_response.vertexArray quad_indices_array = get_grid_surface_response.quadIndicesArr -origin_utm_xy = get_grid_surface_response.originUtmXy source_cell_indices_arr = get_grid_surface_response.sourceCellIndicesArr +origin_utm_xy = get_grid_surface_response.originUtmXy grid_dimensions = get_grid_surface_response.gridDimensions num_vertex_coords = 3 # [x, y, z] num_vertices_per_quad = 4 # [v1, v2, v3, v4] -num_quads = len(vertex_array) / (num_vertex_coords * num_vertices_per_quad) +num_quads = len(quad_indices_array) / num_vertices_per_quad # Create x-, y-, and z-arrays x_array = [] y_array = [] z_array = [] -for i in range(0, len(vertex_array), num_vertex_coords): - x_array.append(vertex_array[i + 0]) - y_array.append(vertex_array[i + 1]) - z_array.append(vertex_array[i + 2]) +for _, vertex_index in enumerate(quad_indices_array, 0): + vertex_array_index = vertex_index * num_vertex_coords + x_array.append(vertex_array[vertex_array_index + 0]) + y_array.append(vertex_array[vertex_array_index + 1]) + z_array.append(vertex_array[vertex_array_index + 2]) # Create triangular mesh i_array = [] @@ -86,7 +87,10 @@ ) +print(f"Number of vertices in vertex array: {len(vertex_array) / 3}") +print(f"Number of quad vertices: {len(quad_indices_array)}") print(f"Number of quads: {num_quads}") + print(f"Source cell indices array length: {len(source_cell_indices_arr)}") print(f"Origin UTM coordinates [x, y]: [{origin_utm_xy.x}, {origin_utm_xy.y}]") print( diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py index 4c8c54092d..51fd09330a 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface_MULTIPLE_REQUESTS.py @@ -17,8 +17,8 @@ # ) ijk_index_filter = None -num_calls = 30 -sleep_time_s = 0.5 +num_calls = 100 +sleep_time_s = 0.1 for i in range(num_calls): print(f"Call {i+1}/{num_calls}") diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 8ad579c440..0152555b22 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -163,35 +163,60 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC { return grpc::Status( grpc::StatusCode::NOT_FOUND, "No grid fault vertices found" ); } + m_elapsedTimeInfo.elapsedTimePerEventMs["CreateGridFaultVertices"] = static_cast( createFaultVerticesTimeCount.elapsedMsCount() ); // Retrieve the UTM offset const auto mainGridModelOffset = m_eclipseCase->mainGrid()->displayModelOffset(); - // Set vertex_array and quadindicesarr response + // Vertex welding + // - Low welding distance, as the goal is to weld duplicate vertices + // - Welding is done for surface and fault vertices separately + const double weldingDistance = 1e-3; + const double weldingCellSize = 4.0 * weldingDistance; + auto weldVerticesTimeCount = ElapsedTimeCount(); + + // Weld surface vertices + cvf::VertexWelder surfaceVertexWelder; + const cvf::uint numSurfaceWelderBuckets = static_cast( gridSurfaceVertices->size() ); + surfaceVertexWelder.initialize( weldingDistance, weldingCellSize, numSurfaceWelderBuckets ); + const auto& surfaceVertexIndices = weldVertices( surfaceVertexWelder, *gridSurfaceVertices ); + + // Weld fault vertices + cvf::VertexWelder faultVertexWelder; + const cvf::uint numFaultWelderBuckets = static_cast( gridFaultVertices->size() ); + faultVertexWelder.initialize( weldingDistance, weldingCellSize, numFaultWelderBuckets ); + const auto& faultVertexIndices = weldVertices( faultVertexWelder, *gridFaultVertices ); + m_elapsedTimeInfo.elapsedTimePerEventMs["WeldVertices"] = + static_cast( weldVerticesTimeCount.elapsedMsCount() ); + + // Fill response auto fillResponseTimeCount = ElapsedTimeCount(); const auto zAxisOffset = mainGridModelOffset.z(); - for ( size_t i = 0; i < gridSurfaceVertices->size(); ++i ) + for ( cvf::uint i = 0; i < surfaceVertexWelder.vertexCount(); ++i ) { - const auto& vertex = gridSurfaceVertices->get( i ); + const auto& vertex = surfaceVertexWelder.vertex( i ); response->add_vertexarray( vertex.x() ); response->add_vertexarray( vertex.y() ); response->add_vertexarray( vertex.z() + zAxisOffset ); - - response->add_quadindicesarr( static_cast( i ) ); + } + for ( const auto& vertexIndex : surfaceVertexIndices ) + { + response->add_quadindicesarr( static_cast( vertexIndex ) ); } - const auto indexOffset = gridSurfaceVertices->size(); - for ( size_t i = 0; i < gridFaultVertices->size(); ++i ) + const cvf::uint vertexIndexOffset = static_cast( surfaceVertexWelder.vertexCount() ); + for ( cvf::uint i = 0; i < faultVertexWelder.vertexCount(); ++i ) { - const auto& vertex = gridFaultVertices->get( i ); + const auto& vertex = faultVertexWelder.vertex( i ); response->add_vertexarray( vertex.x() ); response->add_vertexarray( vertex.y() ); response->add_vertexarray( vertex.z() + zAxisOffset ); - - auto index = indexOffset + i; - response->add_quadindicesarr( static_cast( index ) ); + } + for ( const auto& vertexIndex : faultVertexIndices ) + { + response->add_quadindicesarr( static_cast( vertexIndex + vertexIndexOffset ) ); } // Origin is the UTM offset @@ -401,6 +426,22 @@ std::vector RiaGrpcGridGeometryExtractionService::cre &Self::RequestCutAlongPolyline ) }; } +//-------------------------------------------------------------------------------------------------- +/// Weld vertices and return array of indices of welded vertices +//-------------------------------------------------------------------------------------------------- +std::vector RiaGrpcGridGeometryExtractionService::weldVertices( cvf::VertexWelder& rWelder, + const cvf::Vec3fArray& vertices ) +{ + std::vector vertexIndices; + for ( const auto& vertex : vertices ) + { + bool wasWelded = false; + const auto welderIndex = rWelder.weldVertex( vertex, &wasWelded ); + vertexIndices.push_back( welderIndex ); + } + return vertexIndices; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index f43afe67e9..5eaa148d08 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -28,6 +28,7 @@ #include "cvfArray.h" #include "cvfStructGridGeometryGenerator.h" +#include "cvfVertexWelder.h" #include @@ -63,6 +64,8 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr public: std::vector createCallbacks() override; + static std::vector weldVertices( cvf::VertexWelder& rWelder, const cvf::Vec3fArray& vertices ); + private: void resetInternalPointers(); void tearDownExistingViewsInEclipseCase(); From 7b2a458d318e53977620d9507cf956165dfa95c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Thu, 4 Apr 2024 14:09:11 +0200 Subject: [PATCH 43/45] Minor adjustment - Refactor welding in grid surface endpoint - Add missing include --- .../RivEnclosingPolygonGenerator.cpp | 1 + .../RiaGrpcGridGeometryExtractionService.cpp | 23 ++++++++++--------- .../RiaGrpcGridGeometryExtractionService.h | 8 ++++++- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp index 1d95fd552e..c979c91947 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivEnclosingPolygonGenerator.cpp @@ -19,6 +19,7 @@ #include "RivEnclosingPolygonGenerator.h" #include "cvfMath.h" +#include #include RivEnclosingPolygonGenerator::RivEnclosingPolygonGenerator() diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 0152555b22..6996b3730f 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -179,15 +179,11 @@ grpc::Status RiaGrpcGridGeometryExtractionService::GetGridSurface( grpc::ServerC // Weld surface vertices cvf::VertexWelder surfaceVertexWelder; - const cvf::uint numSurfaceWelderBuckets = static_cast( gridSurfaceVertices->size() ); - surfaceVertexWelder.initialize( weldingDistance, weldingCellSize, numSurfaceWelderBuckets ); - const auto& surfaceVertexIndices = weldVertices( surfaceVertexWelder, *gridSurfaceVertices ); + const auto& surfaceVertexIndices = initAndWeldVertices( surfaceVertexWelder, *gridSurfaceVertices ); // Weld fault vertices cvf::VertexWelder faultVertexWelder; - const cvf::uint numFaultWelderBuckets = static_cast( gridFaultVertices->size() ); - faultVertexWelder.initialize( weldingDistance, weldingCellSize, numFaultWelderBuckets ); - const auto& faultVertexIndices = weldVertices( faultVertexWelder, *gridFaultVertices ); + const auto& faultVertexIndices = initAndWeldVertices( faultVertexWelder, *gridFaultVertices ); m_elapsedTimeInfo.elapsedTimePerEventMs["WeldVertices"] = static_cast( weldVerticesTimeCount.elapsedMsCount() ); @@ -429,17 +425,22 @@ std::vector RiaGrpcGridGeometryExtractionService::cre //-------------------------------------------------------------------------------------------------- /// Weld vertices and return array of indices of welded vertices //-------------------------------------------------------------------------------------------------- -std::vector RiaGrpcGridGeometryExtractionService::weldVertices( cvf::VertexWelder& rWelder, - const cvf::Vec3fArray& vertices ) +std::vector RiaGrpcGridGeometryExtractionService::initAndWeldVertices( cvf::VertexWelder& rWelder, + const cvf::Vec3fArray& vertices ) const { - std::vector vertexIndices; + // Initialize welder + const cvf::uint numBuckets = static_cast( vertices.size() ); + rWelder.initialize( m_weldingDistance, m_weldingCellSize, numBuckets ); + + // Weld vertices + std::vector weldedVertexIndices; for ( const auto& vertex : vertices ) { bool wasWelded = false; const auto welderIndex = rWelder.weldVertex( vertex, &wasWelded ); - vertexIndices.push_back( welderIndex ); + weldedVertexIndices.push_back( welderIndex ); } - return vertexIndices; + return weldedVertexIndices; } //-------------------------------------------------------------------------------------------------- diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h index 5eaa148d08..8ae954aaa5 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.h +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.h @@ -64,7 +64,7 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr public: std::vector createCallbacks() override; - static std::vector weldVertices( cvf::VertexWelder& rWelder, const cvf::Vec3fArray& vertices ); + std::vector initAndWeldVertices( cvf::VertexWelder& rWelder, const cvf::Vec3fArray& vertices ) const; private: void resetInternalPointers(); @@ -85,6 +85,12 @@ class RiaGrpcGridGeometryExtractionService final : public rips::GridGeometryExtr std::unique_ptr m_surfaceFaceVisibilityFilter = nullptr; std::unique_ptr m_faultFaceVisibilityFilter = nullptr; + // Vertex welding + // - Low welding distance, as the goal is to weld duplicate vertices + // - Welding is done for surface and fault vertices separately + const double m_weldingDistance = 1e-3; + const double m_weldingCellSize = 4.0 * m_weldingDistance; + struct ElapsedTimeInfo { std::uint32_t totalTimeElapsedMs = 0; // Total time elapsed for entire request From ecf9e67b680ba0b8a63b66da601ce721ad48698e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 5 Apr 2024 14:59:08 +0200 Subject: [PATCH 44/45] Fix incorrect setting of num buckets --- ...vPolylineIntersectionGeometryGenerator.cpp | 5 +- .../drogon_grid_well_path_polyline_xy_utm.py | 1016 +++++++++++++++++ ..._geometry_extraction_cut_along_polyline.py | 6 + ...id_geometry_extraction_get_grid_surface.py | 7 +- .../RiaGrpcGridGeometryExtractionService.cpp | 2 +- 5 files changed, 1029 insertions(+), 7 deletions(-) create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/drogon_grid_well_path_polyline_xy_utm.py diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index a376f326fd..d62a9c36a8 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -165,10 +165,9 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* std::vector polygonToCellIndexMap = {}; // Welder for segment vertices - // - Number of buckets is size of columnCellCandidates divided by 8 to avoid too many buckets (Random selected value). - // Usage of columnCellCandidates is to get a dynamic number of buckets usable for respective segment. - const cvf::uint numWelderBuckets = static_cast( columnCellCandidates.size() / size_t( 8 ) ); + // - Number of buckets is size of columnCellCandidates to get a dynamic number of buckets usable for respective segment. cvf::VertexWelder segmentVertexWelder; + const cvf::uint numWelderBuckets = std::max( static_cast( columnCellCandidates.size() ), cvf::uint( 1 ) ); segmentVertexWelder.initialize( weldingDistance, weldingCellSize, numWelderBuckets ); // Intersection per grid cell - transform from set of triangles to polygon for cell diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/drogon_grid_well_path_polyline_xy_utm.py b/GrpcInterface/Python/rips/WebvizPythonExamples/drogon_grid_well_path_polyline_xy_utm.py new file mode 100644 index 0000000000..fa9a1c26dd --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/drogon_grid_well_path_polyline_xy_utm.py @@ -0,0 +1,1016 @@ +drogon_well_path_polyline_xy_utm = [ + 463256.911, + 5930542.294, + 463259.476, + 5930546.594, + 463262.041, + 5930550.894, + 463264.606, + 5930555.194, + 463267.172, + 5930559.494, + 463269.737, + 5930563.793, + 463272.302, + 5930568.093, + 463274.867, + 5930572.393, + 463277.433, + 5930576.693, + 463279.998, + 5930580.993, + 463282.563, + 5930585.293, + 463285.129, + 5930589.593, + 463287.694, + 5930593.892, + 463290.259, + 5930598.192, + 463292.825, + 5930602.492, + 463295.39, + 5930606.792, + 463297.955, + 5930611.092, + 463300.521, + 5930615.392, + 463303.086, + 5930619.691, + 463305.651, + 5930623.991, + 463308.217, + 5930628.291, + 463310.782, + 5930632.591, + 463313.347, + 5930636.891, + 463315.913, + 5930641.191, + 463318.478, + 5930645.491, + 463321.043, + 5930649.79, + 463323.608, + 5930654.09, + 463326.174, + 5930658.39, + 463328.739, + 5930662.69, + 463331.304, + 5930666.99, + 463333.87, + 5930671.29, + 463336.435, + 5930675.59, + 463339, + 5930679.889, + 463341.566, + 5930684.189, + 463344.131, + 5930688.489, + 463346.696, + 5930692.789, + 463349.262, + 5930697.089, + 463351.827, + 5930701.389, + 463354.392, + 5930705.689, + 463356.957, + 5930709.988, + 463359.523, + 5930714.288, + 463362.088, + 5930718.588, + 463364.653, + 5930722.888, + 463367.218, + 5930727.188, + 463369.784, + 5930731.488, + 463372.349, + 5930735.788, + 463374.914, + 5930740.088, + 463377.48, + 5930744.388, + 463380.045, + 5930748.687, + 463382.61, + 5930752.987, + 463385.175, + 5930757.287, + 463387.741, + 5930761.587, + 463390.306, + 5930765.887, + 463392.871, + 5930770.187, + 463395.436, + 5930774.487, + 463398.001, + 5930778.787, + 463400.567, + 5930783.087, + 463403.132, + 5930787.387, + 463405.697, + 5930791.686, + 463408.262, + 5930795.986, + 463410.827, + 5930800.286, + 463413.393, + 5930804.586, + 463415.958, + 5930808.886, + 463418.523, + 5930813.186, + 463421.088, + 5930817.486, + 463423.653, + 5930821.786, + 463426.218, + 5930826.086, + 463428.784, + 5930830.386, + 463431.349, + 5930834.686, + 463433.914, + 5930838.986, + 463436.479, + 5930843.286, + 463439.044, + 5930847.586, + 463441.609, + 5930851.886, + 463444.174, + 5930856.186, + 463446.739, + 5930860.486, + 463449.304, + 5930864.786, + 463451.869, + 5930869.086, + 463454.435, + 5930873.386, + 463457, + 5930877.686, + 463459.565, + 5930881.986, + 463462.13, + 5930886.286, + 463464.695, + 5930890.586, + 463467.26, + 5930894.886, + 463469.825, + 5930899.186, + 463472.39, + 5930903.486, + 463474.955, + 5930907.786, + 463477.52, + 5930912.086, + 463480.085, + 5930916.386, + 463482.649, + 5930920.686, + 463485.214, + 5930924.986, + 463487.779, + 5930929.286, + 463490.344, + 5930933.586, + 463492.909, + 5930937.886, + 463495.474, + 5930942.187, + 463498.039, + 5930946.487, + 463500.604, + 5930950.787, + 463503.168, + 5930955.087, + 463505.733, + 5930959.387, + 463508.298, + 5930963.687, + 463510.862, + 5930967.988, + 463513.427, + 5930972.288, + 463515.992, + 5930976.588, + 463518.556, + 5930980.888, + 463521.121, + 5930985.189, + 463523.686, + 5930989.489, + 463526.25, + 5930993.789, + 463528.814, + 5930998.09, + 463531.379, + 5931002.39, + 463533.943, + 5931006.691, + 463536.507, + 5931010.991, + 463539.072, + 5931015.291, + 463541.636, + 5931019.592, + 463544.2, + 5931023.893, + 463546.764, + 5931028.194, + 463549.327, + 5931032.494, + 463551.891, + 5931036.795, + 463554.454, + 5931041.096, + 463557.017, + 5931045.398, + 463559.58, + 5931049.699, + 463562.141, + 5931054.001, + 463564.7, + 5931058.305, + 463567.247, + 5931062.615, + 463569.787, + 5931066.93, + 463572.321, + 5931071.249, + 463574.851, + 5931075.569, + 463577.378, + 5931079.892, + 463579.903, + 5931084.215, + 463582.427, + 5931088.54, + 463584.949, + 5931092.865, + 463587.469, + 5931097.192, + 463589.988, + 5931101.519, + 463592.506, + 5931105.846, + 463595.023, + 5931110.175, + 463597.54, + 5931114.503, + 463600.055, + 5931118.832, + 463602.57, + 5931123.162, + 463605.084, + 5931127.492, + 463607.597, + 5931131.823, + 463610.11, + 5931136.153, + 463612.622, + 5931140.485, + 463615.133, + 5931144.816, + 463617.644, + 5931149.148, + 463620.154, + 5931153.481, + 463622.663, + 5931157.813, + 463625.172, + 5931162.147, + 463627.679, + 5931166.48, + 463630.186, + 5931170.815, + 463632.691, + 5931175.15, + 463635.194, + 5931179.486, + 463637.691, + 5931183.826, + 463640.162, + 5931188.181, + 463642.621, + 5931192.542, + 463645.077, + 5931196.906, + 463647.529, + 5931201.271, + 463649.98, + 5931205.637, + 463652.429, + 5931210.004, + 463654.876, + 5931214.372, + 463657.322, + 5931218.741, + 463659.767, + 5931223.111, + 463662.21, + 5931227.481, + 463664.651, + 5931231.853, + 463667.091, + 5931236.225, + 463669.53, + 5931240.598, + 463671.966, + 5931244.972, + 463674.4, + 5931249.348, + 463676.832, + 5931253.725, + 463679.26, + 5931258.103, + 463681.685, + 5931262.484, + 463684.105, + 5931266.867, + 463686.519, + 5931271.253, + 463688.924, + 5931275.645, + 463691.312, + 5931280.046, + 463693.692, + 5931284.451, + 463696.071, + 5931288.857, + 463698.45, + 5931293.262, + 463700.829, + 5931297.668, + 463703.207, + 5931302.074, + 463705.586, + 5931306.48, + 463707.964, + 5931310.886, + 463710.342, + 5931315.292, + 463712.72, + 5931319.698, + 463715.098, + 5931324.105, + 463717.475, + 5931328.511, + 463719.853, + 5931332.918, + 463722.23, + 5931337.324, + 463724.607, + 5931341.731, + 463726.984, + 5931346.138, + 463729.361, + 5931350.544, + 463731.738, + 5931354.951, + 463734.115, + 5931359.358, + 463736.491, + 5931363.765, + 463738.868, + 5931368.172, + 463741.244, + 5931372.579, + 463743.62, + 5931376.987, + 463745.996, + 5931381.394, + 463748.372, + 5931385.801, + 463750.748, + 5931390.208, + 463753.124, + 5931394.616, + 463755.499, + 5931399.023, + 463757.875, + 5931403.431, + 463760.25, + 5931407.839, + 463762.625, + 5931412.246, + 463765, + 5931416.654, + 463767.375, + 5931421.062, + 463769.75, + 5931425.47, + 463772.124, + 5931429.878, + 463774.499, + 5931434.286, + 463776.873, + 5931438.694, + 463779.247, + 5931443.103, + 463781.622, + 5931447.511, + 463783.995, + 5931451.919, + 463786.369, + 5931456.328, + 463788.743, + 5931460.736, + 463791.116, + 5931465.145, + 463793.489, + 5931469.554, + 463795.862, + 5931473.963, + 463798.235, + 5931478.372, + 463800.608, + 5931482.781, + 463802.981, + 5931487.19, + 463805.353, + 5931491.599, + 463807.725, + 5931496.009, + 463810.097, + 5931500.418, + 463812.469, + 5931504.828, + 463814.84, + 5931509.237, + 463817.211, + 5931513.647, + 463819.583, + 5931518.057, + 463821.953, + 5931522.467, + 463824.324, + 5931526.877, + 463826.694, + 5931531.288, + 463829.064, + 5931535.698, + 463831.434, + 5931540.109, + 463833.804, + 5931544.52, + 463836.173, + 5931548.931, + 463838.542, + 5931553.342, + 463840.91, + 5931557.753, + 463843.279, + 5931562.164, + 463845.647, + 5931566.576, + 463848.014, + 5931570.988, + 463850.381, + 5931575.4, + 463852.748, + 5931579.812, + 463855.114, + 5931584.225, + 463857.48, + 5931588.637, + 463859.846, + 5931593.05, + 463862.211, + 5931597.463, + 463864.575, + 5931601.877, + 463866.939, + 5931606.291, + 463869.302, + 5931610.705, + 463871.665, + 5931615.12, + 463874.026, + 5931619.535, + 463876.387, + 5931623.95, + 463878.748, + 5931628.366, + 463881.107, + 5931632.782, + 463883.465, + 5931637.199, + 463885.822, + 5931641.616, + 463888.178, + 5931646.034, + 463890.532, + 5931650.453, + 463892.885, + 5931654.873, + 463895.236, + 5931659.294, + 463897.585, + 5931663.716, + 463899.93, + 5931668.139, + 463902.273, + 5931672.564, + 463904.612, + 5931676.991, + 463906.945, + 5931681.421, + 463909.27, + 5931685.856, + 463911.582, + 5931690.296, + 463913.886, + 5931694.742, + 463916.187, + 5931699.189, + 463918.486, + 5931703.637, + 463920.783, + 5931708.085, + 463923.08, + 5931712.534, + 463925.376, + 5931716.984, + 463927.671, + 5931721.434, + 463929.966, + 5931725.884, + 463932.261, + 5931730.334, + 463934.555, + 5931734.784, + 463936.849, + 5931739.235, + 463939.143, + 5931743.685, + 463941.437, + 5931748.136, + 463943.73, + 5931752.587, + 463946.023, + 5931757.038, + 463948.316, + 5931761.489, + 463950.609, + 5931765.94, + 463952.902, + 5931770.391, + 463955.195, + 5931774.843, + 463957.487, + 5931779.294, + 463959.78, + 5931783.745, + 463962.072, + 5931788.197, + 463964.364, + 5931792.648, + 463966.656, + 5931797.099, + 463968.948, + 5931801.551, + 463971.24, + 5931806.002, + 463973.532, + 5931810.454, + 463975.824, + 5931814.906, + 463978.116, + 5931819.357, + 463980.407, + 5931823.809, + 463982.699, + 5931828.261, + 463984.99, + 5931832.712, + 463987.282, + 5931837.164, + 463989.573, + 5931841.616, + 463991.865, + 5931846.068, + 463994.156, + 5931850.52, + 463996.448, + 5931854.972, + 463998.739, + 5931859.424, + 464001.03, + 5931863.876, + 464003.321, + 5931868.328, + 464005.613, + 5931872.78, + 464007.904, + 5931877.232, + 464010.195, + 5931881.684, + 464012.486, + 5931886.136, + 464014.777, + 5931890.588, + 464017.068, + 5931895.04, + 464019.359, + 5931899.492, + 464021.65, + 5931903.944, + 464023.941, + 5931908.396, + 464026.231, + 5931912.848, + 464028.522, + 5931917.3, + 464030.813, + 5931921.753, + 464033.104, + 5931926.205, + 464035.395, + 5931930.657, + 464037.685, + 5931935.109, + 464039.976, + 5931939.561, + 464042.267, + 5931944.014, + 464044.557, + 5931948.466, + 464046.848, + 5931952.918, + 464049.139, + 5931957.37, + 464051.429, + 5931961.823, + 464053.72, + 5931966.275, + 464056.01, + 5931970.727, + 464058.301, + 5931975.18, + 464060.591, + 5931979.632, + 464062.882, + 5931984.084, + 464065.172, + 5931988.537, + 464067.463, + 5931992.989, + 464069.753, + 5931997.441, + 464072.043, + 5932001.894, + 464074.334, + 5932006.346, + 464076.624, + 5932010.798, + 464078.915, + 5932015.251, + 464081.205, + 5932019.703, + 464083.495, + 5932024.156, + 464085.786, + 5932028.608, + 464088.076, + 5932033.06, + 464090.366, + 5932037.513, + 464092.656, + 5932041.965, + 464094.947, + 5932046.418, + 464097.237, + 5932050.87, + 464099.527, + 5932055.323, + 464101.817, + 5932059.775, + 464104.108, + 5932064.228, + 464106.398, + 5932068.68, + 464108.688, + 5932073.133, + 464110.978, + 5932077.585, + 464113.268, + 5932082.038, + 464115.558, + 5932086.49, + 464117.848, + 5932090.943, + 464120.139, + 5932095.395, + 464122.429, + 5932099.848, + 464124.719, + 5932104.3, + 464127.009, + 5932108.753, + 464129.299, + 5932113.205, + 464131.589, + 5932117.658, + 464133.879, + 5932122.11, + 464136.169, + 5932126.563, + 464138.459, + 5932131.016, + 464140.749, + 5932135.468, + 464143.039, + 5932139.921, + 464145.329, + 5932144.373, + 464147.619, + 5932148.826, + 464149.909, + 5932153.278, + 464152.199, + 5932157.731, + 464154.489, + 5932162.184, + 464156.779, + 5932166.636, + 464159.069, + 5932171.089, + 464161.359, + 5932175.542, + 464163.648, + 5932179.994, + 464165.938, + 5932184.447, + 464168.228, + 5932188.899, + 464170.518, + 5932193.352, + 464172.808, + 5932197.805, + 464175.098, + 5932202.257, + 464177.388, + 5932206.71, + 464179.678, + 5932211.163, + 464181.967, + 5932215.615, + 464184.257, + 5932220.068, + 464186.547, + 5932224.521, + 464188.837, + 5932228.973, + 464191.127, + 5932233.426, + 464193.417, + 5932237.879, + 464195.706, + 5932242.331, + 464197.996, + 5932246.784, + 464200.286, + 5932251.237, + 464202.576, + 5932255.689, + 464204.865, + 5932260.142, + 464207.155, + 5932264.595, + 464209.445, + 5932269.048, + 464211.735, + 5932273.5, + 464214.024, + 5932277.953, + 464216.314, + 5932282.406, + 464218.604, + 5932286.858, + 464220.894, + 5932291.311, + 464223.183, + 5932295.764, + 464225.473, + 5932300.217, + 464227.763, + 5932304.669, + 464230.052, + 5932309.122, + 464232.342, + 5932313.575, + 464234.632, + 5932318.027, + 464236.921, + 5932322.48, + 464239.211, + 5932326.933, + 464241.501, + 5932331.386, + 464243.79, + 5932335.838, + 464246.08, + 5932340.291, + 464248.37, + 5932344.744, + 464250.659, + 5932349.197, + 464252.949, + 5932353.649, + 464255.239, + 5932358.102, + 464257.528, + 5932362.555, + 464259.818, + 5932367.008, + 464262.108, + 5932371.461, + 464264.397, + 5932375.913, + 464266.687, + 5932380.366, + 464268.976, + 5932384.819, + 464271.266, + 5932389.272, + 464273.556, + 5932393.725, + 464275.845, + 5932398.177, + 464278.135, + 5932402.63, + 464280.424, + 5932407.083, + 464282.714, + 5932411.536, + 464285.003, + 5932415.988, + 464287.293, + 5932420.441, + 464289.583, + 5932424.894, + 464291.872, + 5932429.347, + 464294.162, + 5932433.8, + 464296.451, + 5932438.253, + 464298.741, + 5932442.705, + 464301.03, + 5932447.158, + 464303.32, + 5932451.611, + 464305.609, + 5932456.064, + 464307.899, + 5932460.517, + 464310.188, + 5932464.969, + 464312.478, + 5932469.422, + 464314.767, + 5932473.875, + 464317.057, + 5932478.328, + 464319.346, + 5932482.781, + 464321.636, + 5932487.234, + 464323.926, + 5932491.686, + 464326.215, + 5932496.139, + 464328.505, + 5932500.592, + 464330.794, + 5932505.045, + 464333.083, + 5932509.498, + 464335.373, + 5932513.951, + 464337.662, + 5932518.403, + 464339.952, + 5932522.856, + 464342.241, + 5932527.309, + 464344.531, + 5932531.762, + 464346.82, + 5932536.215, + 464349.11, + 5932540.668, + 464351.399, + 5932545.12, + 464353.689, + 5932549.573, + 464355.978, + 5932554.026, + 464358.268, + 5932558.479, + 464360.557, + 5932562.932, + 464362.847, + 5932567.385, + 464365.136, + 5932571.838, + 464367.426, + 5932576.291, + 464369.715, + 5932580.743, + 464372.004, + 5932585.196, + 464374.294, + 5932589.649, + 464376.583, + 5932594.102, + 464378.873, + 5932598.555, + 464381.162, + 5932603.008, + 464383.452, + 5932607.461, + 464385.741, + 5932611.913, + 464388.031, + 5932616.366, + 464390.32, + 5932620.819, + 464392.61, + 5932625.272, + 464394.899, + 5932629.725, + 464397.188, + 5932634.178, + 464399.478, + 5932638.631, + 464401.767, + 5932643.084, + 464404.057, + 5932647.536, + 464406.346, + 5932651.989, + 464408.636, + 5932656.442, + 464410.925, + 5932660.895, + 464413.214, + 5932665.348, + 464415.504, + 5932669.801, + 464417.794, + 5932674.254, + 464420.083, + 5932678.706, + 464422.372, + 5932683.159, + 464424.662, + 5932687.612, + 464426.951, + 5932692.065, + 464429.241, + 5932696.518, + 464431.53, + 5932700.971, + 464433.82, + 5932705.423, + 464436.109, + 5932709.876, + 464438.399, + 5932714.329, + 464440.688, + 5932718.781, + 464442.978, + 5932723.235, + 464445.268, + 5932727.687, + 464447.557, + 5932732.14, + 464449.847, + 5932736.593, + 464452.137, + 5932741.046, + 464454.426, + 5932745.498, + 464456.716, + 5932749.951, + 464459.006, + 5932754.404, + 464461.296, + 5932758.857, + 464463.586, + 5932763.309, + 464465.876, + 5932767.761, +] diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index 408450d219..2c856381b6 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -10,6 +10,8 @@ # from ..generated.GridGeometryExtraction_pb2_grpc import * # from ..generated.GridGeometryExtraction_pb2 import * +from drogon_grid_well_path_polyline_xy_utm import drogon_well_path_polyline_xy_utm + rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) @@ -17,6 +19,7 @@ grid_file_name = ( "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" ) +grid_file_name = "D:/ResInsight/GRID__DROGON_13M.roff" # Test polylines mocked_model_fence_poly_line_utm_xy = [ @@ -235,4 +238,7 @@ for message, time_elapsed in named_events_and_time_elapsed.items(): print(f"{message}: {time_elapsed}") +print(f"Expected number of segments: {len(fence_poly_line_utm_xy) / 2 - 1}") +print(f"Number of segments: {len(fence_mesh_sections)}") + fig.show() diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py index 13ab667899..1f36671066 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_get_grid_surface.py @@ -13,11 +13,12 @@ rips_instance = Instance.find() grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) -grid_file_name = ( - "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" -) +# grid_file_name = ( +# "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" +# ) # grid_file_name = "MOCKED_TEST_GRID" # grid_file_name = "D:/ResInsight/GRID__SNORRE_BASECASEGRID.roff" +grid_file_name = "D:/ResInsight/GRID__DROGON_13M.roff" ijk_index_filter = GridGeometryExtraction__pb2.IJKIndexFilter( iMin=15, iMax=30, jMin=30, jMax=90, kMin=1, kMax=12 diff --git a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp index 6996b3730f..f08ab49607 100644 --- a/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp +++ b/GrpcInterface/RiaGrpcGridGeometryExtractionService.cpp @@ -429,7 +429,7 @@ std::vector RiaGrpcGridGeometryExtractionService::initAndWeldVertices const cvf::Vec3fArray& vertices ) const { // Initialize welder - const cvf::uint numBuckets = static_cast( vertices.size() ); + const cvf::uint numBuckets = std::max( static_cast( vertices.size() ), cvf::uint( 1 ) ); rWelder.initialize( m_weldingDistance, m_weldingCellSize, numBuckets ); // Weld vertices From d4dddb0c95c8611751e5746221c0ffd49ebf1cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Herje?= Date: Fri, 5 Apr 2024 17:05:21 +0200 Subject: [PATCH 45/45] Backup --- ...vPolylineIntersectionGeometryGenerator.cpp | 2 +- ...action_cut_along_polyline NUM_SEGMENTSy.py | 106 ++++++++++++++++++ ..._geometry_extraction_cut_along_polyline.py | 33 +++++- GrpcInterface/Python/rips/instance.py | 12 +- 4 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline NUM_SEGMENTSy.py diff --git a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp index d62a9c36a8..87e2333af5 100644 --- a/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp +++ b/ApplicationLibCode/ModelVisualization/Intersections/RivPolylineIntersectionGeometryGenerator.cpp @@ -105,7 +105,7 @@ void RivPolylineIntersectionGeometryGenerator::calculateArrays( cvf::UByteArray* // - Low welding distance, as the goal is to weld duplicate vertices // - Number of buckets is set per segment, utilizing number of cells intersecting the segment const double weldingDistance = 1.0e-3; - const double weldingCellSize = 4.0 * weldingDistance; + const double weldingCellSize = 20.0 * weldingDistance; const size_t numPoints = m_polylineUtm.size(); size_t pointIdx = 0; diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline NUM_SEGMENTSy.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline NUM_SEGMENTSy.py new file mode 100644 index 0000000000..cc8b41f46e --- /dev/null +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline NUM_SEGMENTSy.py @@ -0,0 +1,106 @@ +import numpy as np + +import plotly.graph_objects as go + +from rips.instance import * +from rips.generated.GridGeometryExtraction_pb2_grpc import * +from rips.generated.GridGeometryExtraction_pb2 import * + +# from ..instance import * +# from ..generated.GridGeometryExtraction_pb2_grpc import * +# from ..generated.GridGeometryExtraction_pb2 import * + +from drogon_grid_well_path_polyline_xy_utm import drogon_well_path_polyline_xy_utm + +rips_instance = Instance.find() +grid_geometry_extraction_stub = GridGeometryExtractionStub(rips_instance.channel) + +grid_file_name = "MOCKED_TEST_GRID" +grid_file_name = ( + "D:/Git/resinsight-tutorials/model-data/norne/NORNE_ATW2013_RFTPLT_V2.EGRID" +) +grid_file_name = "D:/ResInsight/GRID__DROGON_13M.roff" + +# Test polylines +mocked_model_fence_poly_line_utm_xy = [ + 11.2631, + 11.9276, + 14.1083, + 18.2929, + 18.3523, + 10.9173, +] +norne_case_fence_poly_line_utm_xy = [ + 456221, + 7.32113e06, + 457150, + 7.32106e06, + 456885, + 7.32176e06, + 457648, + 7.3226e06, + 458805, + 7.32278e06, +] +norne_case_single_segment_poly_line_utm_xy = [457150, 7.32106e06, 456885, 7.32176e06] +norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] + +# Drogon 13M case + +# Polyline along J-direction with I-index = 6 +drogon_13M_start_utm_xy = [456189, 5.93605e06] +drogon_13M_end_utm_xy = [461625, 5.92663e06] +num_j_samples = 438 + +# Polyline random +# drogon_13M_start_utm_xy = [457026, 5.93502e06] +# drogon_13M_end_utm_xy = [466228, 5.93108e06] + +num_polyline_samples = 10 +drogon_13M_case_poly_line_utm_xy = [ + drogon_13M_start_utm_xy[0], + drogon_13M_start_utm_xy[1], +] +for i in range(1, num_polyline_samples): + x = drogon_13M_start_utm_xy[0] + (i / num_polyline_samples) * ( + drogon_13M_end_utm_xy[0] - drogon_13M_start_utm_xy[0] + ) + y = drogon_13M_start_utm_xy[1] + (i / num_polyline_samples) * ( + drogon_13M_end_utm_xy[1] - drogon_13M_start_utm_xy[1] + ) + + drogon_13M_case_poly_line_utm_xy.append(x) + drogon_13M_case_poly_line_utm_xy.append(y) +drogon_13M_case_poly_line_utm_xy.append(drogon_13M_end_utm_xy[0]) +drogon_13M_case_poly_line_utm_xy.append(drogon_13M_end_utm_xy[1]) + +fence_poly_line_utm_xy = drogon_13M_case_poly_line_utm_xy + +cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( + gridFilename=grid_file_name, + fencePolylineUtmXY=fence_poly_line_utm_xy, +) +cut_along_polyline_response: GridGeometryExtraction__pb2.CutAlongPolylineResponse = ( + grid_geometry_extraction_stub.CutAlongPolyline(cut_along_polyline_request) +) + +total_time_elapsed = cut_along_polyline_response.timeElapsedInfo.totalTimeElapsedMs +named_events_and_time_elapsed = ( + cut_along_polyline_response.timeElapsedInfo.namedEventsAndTimeElapsedMs +) + +fence_mesh_sections = cut_along_polyline_response.fenceMeshSections +print(f"Number of fence mesh sections: {len(fence_mesh_sections)}") + +num_polygons = 0 +for section in fence_mesh_sections: + vertices_per_polygon = section.verticesPerPolygonArr + num_polygons += len(vertices_per_polygon) + +print(f"Total time elapsed: {total_time_elapsed} ms") +for message, time_elapsed in named_events_and_time_elapsed.items(): + print(f"{message}: {time_elapsed}") + +print(f"Expected number of segments: {len(fence_poly_line_utm_xy) / 2 - 1}") +print(f"Number of segments: {len(fence_mesh_sections)}") +print(f"Number of polygons: {num_polygons}") diff --git a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py index 2c856381b6..f4252a5dd6 100644 --- a/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py +++ b/GrpcInterface/Python/rips/WebvizPythonExamples/grid_geometry_extraction_cut_along_polyline.py @@ -46,8 +46,29 @@ norne_case_single_segment_poly_line_gap_utm_xy = [460877, 7.3236e06, 459279, 7.32477e06] -# fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy -fence_poly_line_utm_xy = norne_case_fence_poly_line_utm_xy +# Drogon 13M case +drogon_13M_start_utm_xy = [457026, 5.93502e06] +drogon_13M_end_utm_xy = [466228, 5.93108e06] + +num_polyline_samples = 300 +drogon_13M_case_poly_line_utm_xy = [ + drogon_13M_start_utm_xy[0], + drogon_13M_start_utm_xy[1], +] +for i in range(1, num_polyline_samples): + x = drogon_13M_start_utm_xy[0] + (i / num_polyline_samples) * ( + drogon_13M_end_utm_xy[0] - drogon_13M_start_utm_xy[0] + ) + y = drogon_13M_start_utm_xy[1] + (i / num_polyline_samples) * ( + drogon_13M_end_utm_xy[1] - drogon_13M_start_utm_xy[1] + ) + + drogon_13M_case_poly_line_utm_xy.append(x) + drogon_13M_case_poly_line_utm_xy.append(y) +drogon_13M_case_poly_line_utm_xy.append(drogon_13M_end_utm_xy[0]) +drogon_13M_case_poly_line_utm_xy.append(drogon_13M_end_utm_xy[1]) + +fence_poly_line_utm_xy = drogon_13M_case_poly_line_utm_xy cut_along_polyline_request = GridGeometryExtraction__pb2.CutAlongPolylineRequest( gridFilename=grid_file_name, @@ -72,6 +93,7 @@ x_origin = fence_mesh_sections[0].startUtmXY.x if len(fence_mesh_sections) > 0 else 0 y_origin = fence_mesh_sections[0].startUtmXY.y if len(fence_mesh_sections) > 0 else 0 + section_number = 1 for section in fence_mesh_sections: # Continue to next section @@ -82,8 +104,10 @@ num_vertices = sum(vertices_per_polygon) print(f"**** Section number: {section_number} ****") print(f"Number of vertices in vertex uz array: {len(polygon_vertex_array_uz)/2}") - print(f"Number of polygon vertices: {len(polygon_indices_array)}") - print(f"Number of vertices: {num_vertices}") + # print(f"Number of polygon vertices: {len(polygon_indices_array)}") + # print(f"Number of vertices: {num_vertices}") + # print(f"Number of polygons: {len(vertices_per_polygon)}") + section_number += 1 # Get start and end coordinates (local coordinates) @@ -241,4 +265,5 @@ print(f"Expected number of segments: {len(fence_poly_line_utm_xy) / 2 - 1}") print(f"Number of segments: {len(fence_mesh_sections)}") + fig.show() diff --git a/GrpcInterface/Python/rips/instance.py b/GrpcInterface/Python/rips/instance.py index 29a96fd614..4bcb6041a4 100644 --- a/GrpcInterface/Python/rips/instance.py +++ b/GrpcInterface/Python/rips/instance.py @@ -52,7 +52,11 @@ def __is_port_in_use(port: int) -> bool: def __is_valid_port(port: int) -> bool: location = "localhost:" + str(port) channel = grpc.insecure_channel( - location, options=[("grpc.enable_http_proxy", False)] + location, + options=[ + ("grpc.enable_http_proxy", False), + ("grpc.max_receive_message_length", 512 * 1024 * 1024), + ], ) app = App_pb2_grpc.AppStub(channel) try: @@ -218,7 +222,11 @@ def __init__(self, port: int = 50051, launched: bool = False) -> None: self.location: str = "localhost:" + str(port) self.channel = grpc.insecure_channel( - self.location, options=[("grpc.enable_http_proxy", False)] + self.location, + options=[ + ("grpc.enable_http_proxy", False), + ("grpc.max_receive_message_length", 512 * 1024 * 1024), + ], ) self.launched = launched self.commands = Commands_pb2_grpc.CommandsStub(self.channel)