From 01a1f660e76056d46ba7bc9bbddcd09e95786605 Mon Sep 17 00:00:00 2001 From: Gaute Lindkvist Date: Wed, 18 Apr 2018 11:09:50 +0200 Subject: [PATCH] 3D Well Log Curves (#2746): Handle set scale. * Transform to display coordinates *before* calculating normals and generating curves. --- .../Riv3dWellLogCurveGeomertyGenerator.cpp | 21 +++++++---- .../Riv3dWellLogGridGeomertyGenerator.cpp | 36 +++++++++++-------- .../RigWellPathGeometryTools.cpp | 17 ++++----- .../RigWellPathGeometryTools.h | 4 +-- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/ApplicationCode/ModelVisualization/Riv3dWellLogCurveGeomertyGenerator.cpp b/ApplicationCode/ModelVisualization/Riv3dWellLogCurveGeomertyGenerator.cpp index 434a2132d5..4157ee7df9 100644 --- a/ApplicationCode/ModelVisualization/Riv3dWellLogCurveGeomertyGenerator.cpp +++ b/ApplicationCode/ModelVisualization/Riv3dWellLogCurveGeomertyGenerator.cpp @@ -107,22 +107,30 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std RimWellPathCollection* wellPathCollection = nullptr; m_wellPath->firstAncestorOrThisOfTypeAsserted(wellPathCollection); - double maxZClipHeight = wellPathGeometry()->m_wellPathPoints.front().z(); + cvf::Vec3d clipLocation = wellPathGeometry()->m_wellPathPoints.front(); if (wellPathCollection->wellPathClip) { - maxZClipHeight = wellPathClipBoundingBox.max().z() + wellPathCollection->wellPathClipZDistance; + double clipZDistance = wellPathCollection->wellPathClipZDistance; + clipLocation = wellPathClipBoundingBox.max() + clipZDistance * cvf::Vec3d(0, 0, 1); + } + clipLocation = displayCoordTransform->transformToDisplayCoord(clipLocation); + + std::vector wellPathPoints = wellPathGeometry()->m_wellPathPoints; + for (cvf::Vec3d& wellPathPoint : wellPathPoints) + { + wellPathPoint = displayCoordTransform->transformToDisplayCoord(wellPathPoint); } - std::vector wellPathCurveNormals = RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle); + std::vector wellPathCurveNormals = RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathPoints, planeAngle); std::vector interpolatedWellPathPoints; std::vector interpolatedCurveNormals; // Iterate from bottom of well path and up to be able to stop at given Z max clipping height for (auto md = resultMds.rbegin(); md != resultMds.rend(); md++) { - cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(*md); + cvf::Vec3d point = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathPoints, *md); cvf::Vec3d normal = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathCurveNormals, *md); - if (point.z() > maxZClipHeight) break; + if (point.z() > clipLocation.z()) break; interpolatedWellPathPoints.push_back(point); interpolatedCurveNormals.push_back(normal.getNormalized()); @@ -162,8 +170,7 @@ void Riv3dWellLogCurveGeometryGenerator::createCurveVerticesAndIndices(const std planeOffsetFromWellPathCenter + (resultValuesForInterpolatedPoints[i] - minResult) * plotRangeToResultRangeFactor; } - (*vertices)[i] = cvf::Vec3f( - displayCoordTransform->transformToDisplayCoord(interpolatedWellPathPoints[i] + scaledResult * interpolatedCurveNormals[i])); + (*vertices)[i] = cvf::Vec3f(interpolatedWellPathPoints[i] + scaledResult * interpolatedCurveNormals[i]); } std::vector> valuesIntervals = diff --git a/ApplicationCode/ModelVisualization/Riv3dWellLogGridGeomertyGenerator.cpp b/ApplicationCode/ModelVisualization/Riv3dWellLogGridGeomertyGenerator.cpp index 350250ea1e..72a8c77af8 100644 --- a/ApplicationCode/ModelVisualization/Riv3dWellLogGridGeomertyGenerator.cpp +++ b/ApplicationCode/ModelVisualization/Riv3dWellLogGridGeomertyGenerator.cpp @@ -74,15 +74,26 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform* return false; } + for (cvf::Vec3d& wellPathPoint : wellPathPoints) + { + wellPathPoint = displayCoordTransform->transformToDisplayCoord(wellPathPoint); + } + + std::vector wellPathSegmentNormals = + RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathPoints, planeAngle); + + size_t originalWellPathSize = wellPathPoints.size(); if (wellPathCollection->wellPathClip) { + double clipZDistance = wellPathCollection->wellPathClipZDistance; double horizontalLengthAlongWellToClipPoint; - double maxZClipHeight = wellPathClipBoundingBox.max().z() + wellPathCollection->wellPathClipZDistance; + cvf::Vec3d clipLocation = wellPathClipBoundingBox.max() + clipZDistance * cvf::Vec3d(0, 0, 1); + clipLocation = displayCoordTransform->transformToDisplayCoord(clipLocation); size_t indexToFirstVisibleSegment; wellPathPoints = RigWellPath::clipPolylineStartAboveZ( - wellPathPoints, maxZClipHeight, &horizontalLengthAlongWellToClipPoint, &indexToFirstVisibleSegment); + wellPathPoints, clipLocation.z(), &horizontalLengthAlongWellToClipPoint, &indexToFirstVisibleSegment); } if (wellPathPoints.size() < (size_t) 2) @@ -91,9 +102,8 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform* return false; } - // calculateLineSegmentNormals returns normals for the whole well path. Erase the part which is clipped off - std::vector wellPathSegmentNormals = - RigWellPathGeometryTools::calculateLineSegmentNormals(wellPathGeometry(), planeAngle); + // Note that normals are calculated on the full non-clipped well path to increase the likelihood of creating good normals + // for the end points of the curve. So we need to clip the remainder here. wellPathSegmentNormals.erase(wellPathSegmentNormals.begin(), wellPathSegmentNormals.end() - wellPathPoints.size()); { @@ -106,10 +116,10 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform* // Vertices are used for both surface and border for (size_t i = 0; i < wellPathPoints.size(); i++) { - vertices.push_back(cvf::Vec3f(displayCoordTransform->transformToDisplayCoord( - wellPathPoints[i] + wellPathSegmentNormals[i] * planeOffsetFromWellPathCenter))); - vertices.push_back(cvf::Vec3f(displayCoordTransform->transformToDisplayCoord( - wellPathPoints[i] + wellPathSegmentNormals[i] * (planeOffsetFromWellPathCenter + planeWidth)))); + vertices.push_back(cvf::Vec3f( + wellPathPoints[i] + wellPathSegmentNormals[i] * planeOffsetFromWellPathCenter)); + vertices.push_back(cvf::Vec3f( + wellPathPoints[i] + wellPathSegmentNormals[i] * (planeOffsetFromWellPathCenter + planeWidth))); backgroundIndices.push_back((cvf::uint) (2 * i)); backgroundIndices.push_back((cvf::uint) (2 * i + 1)); } @@ -177,7 +187,7 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform* double md = lastMd; while (md >= firstMd) { - cvf::Vec3d point = wellPathGeometry()->interpolatedPointAlongWellPath(md); + cvf::Vec3d point = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathPoints, md); cvf::Vec3d curveNormal = wellPathGeometry()->interpolatedVectorAlongWellPath(wellPathSegmentNormals, md); interpolatedGridPoints.push_back(point); interpolatedGridCurveNormals.push_back(curveNormal.getNormalized()); @@ -193,11 +203,9 @@ Riv3dWellLogGridGeometryGenerator::createGrid(const caf::DisplayCoordTransform* // Normal lines. Start from one to avoid drawing at surface edge. for (size_t i = 1; i < interpolatedGridCurveNormals.size(); i++) { - vertices.push_back(cvf::Vec3f( - displayCoordTransform->transformToDisplayCoord(interpolatedGridPoints[i] + interpolatedGridCurveNormals[i] * planeOffsetFromWellPathCenter))); + vertices.push_back(cvf::Vec3f(interpolatedGridPoints[i] + interpolatedGridCurveNormals[i] * planeOffsetFromWellPathCenter)); - vertices.push_back(cvf::Vec3f(displayCoordTransform->transformToDisplayCoord( - interpolatedGridPoints[i] + interpolatedGridCurveNormals[i] * (planeOffsetFromWellPathCenter + planeWidth)))); + vertices.push_back(cvf::Vec3f(interpolatedGridPoints[i] + interpolatedGridCurveNormals[i] * (planeOffsetFromWellPathCenter + planeWidth))); indices.push_back(indexCounter++); indices.push_back(indexCounter++); diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.cpp b/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.cpp index bc092b58a1..f7e1fcff60 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.cpp +++ b/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.cpp @@ -29,22 +29,18 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector RigWellPathGeometryTools::calculateLineSegmentNormals(const RigWellPath* wellPathGeometry, +std::vector RigWellPathGeometryTools::calculateLineSegmentNormals(const std::vector& vertices, double planeAngle) { std::vector pointNormals; - if (!wellPathGeometry) return pointNormals; - - const std::vector& vertices = wellPathGeometry->wellPathPoints(); - if (vertices.empty()) return pointNormals; pointNormals.reserve(vertices.size()); cvf::Vec3d up(0, 0, 1); - cvf::Vec3d dominantDirection = estimateDominantDirectionInXYPlane(wellPathGeometry); + cvf::Vec3d dominantDirection = estimateDominantDirectionInXYPlane(vertices); const cvf::Vec3d projectionPlaneNormal = (up ^ dominantDirection).getNormalized(); CVF_ASSERT(projectionPlaneNormal * dominantDirection <= std::numeric_limits::epsilon()); @@ -130,13 +126,12 @@ std::vector RigWellPathGeometryTools::interpolateUndefinedNormals(co return interpolated; } -cvf::Vec3d RigWellPathGeometryTools::estimateDominantDirectionInXYPlane(const RigWellPath* wellPathGeometry) +cvf::Vec3d RigWellPathGeometryTools::estimateDominantDirectionInXYPlane(const std::vector& vertices) { - cvf::Vec3d directionSum(0, 0, 0); - const std::vector& points = wellPathGeometry->m_wellPathPoints; - for (size_t i = 1; i < points.size(); ++i) + cvf::Vec3d directionSum(0, 0, 0); + for (size_t i = 1; i < vertices.size(); ++i) { - cvf::Vec3d vec = points[i] - points[i - 1]; + cvf::Vec3d vec = vertices[i] - vertices[i - 1]; vec.z() = 0.0; if (directionSum.length() > 0.0 && (directionSum * vec) < 0.0) { diff --git a/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.h b/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.h index 17cd410a79..658605280b 100644 --- a/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.h +++ b/ApplicationCode/ReservoirDataModel/RigWellPathGeometryTools.h @@ -38,11 +38,11 @@ public: }; public: - static std::vector calculateLineSegmentNormals(const RigWellPath* wellPathGeometry, + static std::vector calculateLineSegmentNormals(const std::vector& vertices, double angle); private: static std::vector interpolateUndefinedNormals(const cvf::Vec3d& planeNormal, const std::vector& normals, const std::vector& vertices); - static cvf::Vec3d estimateDominantDirectionInXYPlane(const RigWellPath* wellPathGeometry); + static cvf::Vec3d estimateDominantDirectionInXYPlane(const std::vector& vertices); };